Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Microservices sind ein beliebtes Architekturkonzept für die Erstellung robuster, hochgradig skalierbarer, unabhängig bereitstellbarer Anwendungen, die sich schnell weiterentwickeln lassen. Der Aufbau einer erfolgreichen Microservices-Architektur erfordert eine grundlegende Veränderung der Denkweise. Es geht über die Dekompilierung einer Anwendung in kleinere Dienste hinaus. Sie müssen auch überdenken, wie Systeme entworfen, bereitgestellt und betrieben werden.
Eine Microservicearchitektur besteht aus einer Sammlung kleiner, autonomer Dienste. Jeder Dienst ist eigenständig und sollte eine einzige Geschäftsfunktion in einem begrenzten Kontext implementieren. Ein begrenzter Kontext ist eine natürliche Unterteilung innerhalb eines Unternehmens und stellt eine explizite Grenze dar, in der ein Domänenmodell vorhanden ist.
Was sind Microservices?
Microservices sind kleine, unabhängige und lose gekoppelte Komponenten, die ein einzelnes kleines Entwicklerteam schreiben und verwalten kann. Jeder Dienst wird als separate Codebasis verwaltet, sodass ein kleines Team ihn effizient verarbeiten kann. Da Dienste unabhängig bereitgestellt werden können, können Teams vorhandene Dienste aktualisieren, ohne die gesamte Anwendung neu zu erstellen oder erneut bereitzustellen. Im Gegensatz zu herkömmlichen Modellen mit einer zentralen Datenebene sind Microservices für die Beibehaltung ihrer eigenen Daten oder des externen Zustands verantwortlich. Sie kommunizieren über gut definierte APIs, wodurch interne Implementierungen von anderen Diensten verborgen bleiben. Diese Architektur unterstützt auch die Polyglot-Programmierung, was bedeutet, dass Dienste nicht denselben Technologiestapel, Bibliotheken oder Frameworks gemeinsam nutzen müssen.
Komponenten
Neben den Diensten selbst erscheinen andere Komponenten in einer typischen Microservices-Architektur:
Verwaltung oder Orchestrierung: Diese Verwaltungskomponente behandelt die Mikroservices-Orchestrierung. Er plant und stellt Dienste über Knoten hinweg bereit, erkennt Fehler, behebt Fehler und ermöglicht die automatische Skalierung bei Bedarf. Eine Container-Orchestrierungsplattform wie Kubernetes bietet diese Funktionalität in der Regel. In cloudeigenen Umgebungen bieten Lösungen wie Azure Container-Apps verwaltete Orchestrierung und integrierte Skalierung. Diese Tools reduzieren die Bereitstellungskomplexität und den Betriebsaufwand.
API-Gateway: Das API-Gateway dient als Einstiegspunkt für Clients. Clients senden Anforderungen an das API-Gateway, anstatt Dienste direkt aufzurufen. Das Gateway leitet diese Anforderungen an die entsprechenden Back-End-Dienste weiter. Darüber hinaus behandelt sie übergreifende Bedenken wie Authentifizierung, Protokollierung und Lastenausgleich. In Cloud-nativen Microservices-Architekturen unterstützen einfache Dienstproxys wie Envoy und Nginx interne Dienst-zu-Dienst-Kommunikation. Diese Art von internem Datenverkehr, der als Ost-West-Verkehr bezeichnet wird, ermöglicht erweiterte Routing- und Datenverkehrskontrolle.
Nachrichtenorientierte Middleware: Messaging-Plattformen wie Apache Kafka und Azure Service Bus ermöglichen die asynchrone Kommunikation in Microservices, indem sie lose Kopplung fördern und hohe Skalierbarkeit unterstützen. Sie bilden die Grundlage von ereignisgesteuerten Architekturen. Mit diesem Ansatz können Dienste auf Ereignisse in Echtzeit reagieren und über asynchrones Messaging kommunizieren.
Observability: Eine effektive Observability-Strategie hilft Teams dabei, die Systemsicherheit aufrechtzuerhalten und Probleme schnell zu lösen. Die zentralisierte Protokollierung vereint Protokolle, um die Diagnose zu vereinfachen. Echtzeitüberwachung mit Anwendungsleistungsüberwachungs-Agents und Frameworks wie OpenTelemetry bietet Einblicke in die Systemintegrität und -leistung. Verteilte Ablaufverfolgung verfolgt Anfragen über Dienstgrenzen hinweg. Es hilft Teams dabei, Engpässe zu finden und die Leistung zu verbessern.
Datenmanagement: Eine gut gestaltete Datenbankarchitektur unterstützt Autonomie und Skalierbarkeit. Microservices verwenden häufig polyglot persistenz, indem verschiedene Datenbanktypen wie SQL oder NoSQL ausgewählt werden, basierend auf den spezifischen Anforderungen der einzelnen Dienste. Dieser Ansatz richtet sich an den domänengesteuerten Entwurf (DDD) und die Idee des gebundenen Kontexts. Jeder Dienst besitzt seine Daten und sein Schema. Dieser Besitz reduziert dienstübergreifende Abhängigkeiten und ermöglicht es Diensten, sich unabhängig voneinander zu entwickeln. Dieses dezentrale Modell verbessert Flexibilität, Leistung und Systemresilienz.
Vorteile
Gewandtheit: Da Microservices unabhängig bereitgestellt werden, ist es einfacher, Fehlerbehebungen und Featureversionen zu verwalten. Sie können einen Dienst aktualisieren, ohne die gesamte Anwendung erneut bereitzustellen und ein Update zurückzusetzen, wenn ein Fehler auftritt. Wenn Sie in vielen herkömmlichen Anwendungen einen Fehler in einem Teil der Anwendung finden, kann der gesamte Releaseprozess blockiert werden. Beispielsweise kann ein Fehler neue Features blockieren, wenn Sie eine Fehlerkorrektur integrieren, testen und veröffentlichen müssen.
Kleine, fokussierte Teams: Ein Microservice sollte klein genug sein, damit ein einzelnes Featureteam es erstellen, testen und bereitstellen kann. Kleinere Teams sind agiler. Große Teams neigen dazu, weniger produktiv zu sein, da die Kommunikation langsamer ist, der Verwaltungsaufwand erhöht und die Flexibilität verringert wird.
Kleine Codebasis: In einer monolithischen Anwendung werden Codeabhängigkeiten im Lauf der Zeit oft unübersichtlich. Das Hinzufügen eines neuen Features erfordert möglicherweise Änderungen in vielen Teilen der Codebasis. Eine Microservices-Architektur vermeidet dieses Problem, indem Code oder Datenspeicher nicht freigegeben werden. Dieser Ansatz minimiert Abhängigkeiten und erleichtert die Einführung neuer Features.
Mischung aus Technologien: Teams können die Technologie auswählen, die am besten zu ihrem Dienst passt, indem sie eine Mischung aus Technologiestapeln entsprechend verwenden.
Fehlerisolation: Wenn ein einzelner Microservice nicht verfügbar ist, wird die gesamte Anwendung nicht gestört, solange alle upstream-Microservices so konzipiert sind, dass Fehler ordnungsgemäß verarbeitet werden. Sie können z. B. das Schaltkreistrennmuster implementieren oder Ihre Lösung so entwerfen, dass die Microservices miteinander kommunizieren, indem Sie asynchrone Messagingmuster verwenden.
Skalierbarkeit: Dienste können unabhängig voneinander skaliert werden. Mit diesem Ansatz können Sie Subsysteme skalieren, die mehr Ressourcen erfordern, ohne die gesamte Anwendung zu skalieren. Verwenden Sie einen Orchestrator wie Kubernetes, um eine höhere Dichte von Diensten auf einem einzelnen Host hinzuzufügen, was eine effizientere Ressourcennutzung ermöglicht.
Datenisolation: Das Aktualisieren eines Schemas ist in einer Microservices-Architektur einfacher, da nur ein Microservice betroffen ist. Im Gegensatz dazu können monolithische Anwendungen Schemaänderungen erschweren, da mehrere Komponenten häufig mit denselben Daten interagieren. Durch diesen freigegebenen Zugriff können Änderungen potenziell riskant sein.
Herausforderungen
Die Vorteile von Microservices kommen mit Kompromissen. Berücksichtigen Sie die folgenden Herausforderungen, bevor Sie eine Microservices-Architektur erstellen:
Kompliziertheit: Eine Microservices-Anwendung verfügt über mehr bewegliche Teile als die entsprechende monolithische Anwendung. Jeder Dienst für sich genommen ist einfacher, aber das System als Ganzes ist komplexer. Stellen Sie sicher, dass Sie Herausforderungen wie Service Discovery, Datenkonsistenz, Transaktionsverwaltung und Interservicekommunikation berücksichtigen, wenn Sie Ihre Anwendung entwerfen.
Entwicklung und Tests: Das Schreiben eines kleinen Diensts, der auf anderen abhängigen Diensten basiert, erfordert einen anderen Ansatz als das Schreiben einer herkömmlichen monolithischen oder mehrschichtigen Anwendung. Vorhandene Tools sind nicht immer für die Arbeit mit Dienstabhängigkeiten ausgelegt. Refactoring über Dienstgrenzen hinweg kann schwierig sein. Es ist auch schwierig, Dienstabhängigkeiten zu testen, insbesondere, wenn sich die Anwendung schnell weiterentwickelt.
Mangel an Governance: Der dezentrale Ansatz zum Aufbau von Microservices hat Vorteile, kann aber auch zu Problemen führen. Es könnte passieren, dass so viele verschiedene Sprachen und Frameworks verwendet werden, dass die Verwaltung der Anwendung schwierig wird. Es empfiehlt sich möglicherweise, einige für das gesamte Projekt gültige Standards zu etablieren, ohne die Agilität der Teams zu sehr einzuschränken. Diese Methode gilt insbesondere für querschneidende Funktionen wie die Protokollierung.
Netzwerküberlastung und Latenz: Die Verwendung vieler kleiner, granularer Dienste kann zu mehr Interservicekommunikation führen. Auch wenn die Kette der Dienstabhängigkeiten zu lang wird (Dienst A ruft B auf, das C aufruft...), kann die zusätzliche Latenz zu einem Problem werden. Sie müssen APIs sorgfältig entwerfen. Vermeiden Sie übermäßig chatzige APIs, denken Sie an Serialisierungsformate und suchen Sie nach Orten, um asynchrone Kommunikationsmuster wie das Queue-Based Load Leveling-Muster zu verwenden.
Datenintegrität: Jeder Microservice ist für die eigene Datenpersistenz verantwortlich. Dadurch kann die Sicherstellung der Datenkonsistenz über mehrere Dienste hinweg zu einer Herausforderung werden. Unterschiedliche Dienste speichern Daten zu unterschiedlichen Zeiten, mithilfe unterschiedlicher Technologien, wobei der Erfolgsfaktor variiert. Wenn mehr als ein Microservice daran beteiligt ist, neue oder geänderte Daten beizubehalten, ist es unwahrscheinlich, dass die vollständige Datenänderung als eine atomige, konsistente, isolierte und dauerhafte Transaktion (ACID) betrachtet werden könnte. Stattdessen ist die Technik stärker auf Basically Available, Soft State, Eventual Consistency (BASE), ausgerichtet. Implementieren Sie die letztliche Konsistenz, wo immer möglich.
Management: Eine erfolgreiche Microservice-Architektur erfordert eine ausgereifte DevOps-Kultur. Die korrelierte Protokollierung über Dienste hinweg kann eine Herausforderung sein. In der Regel muss die Protokollierung mehrere Dienstaufrufe für einen einzigen Benutzervorgang korrelieren.
Versionsverwaltung: Updates für einen Dienst dürfen keine Dienste unterbrechen, die davon abhängig sind. Dienste können jederzeit aktualisiert werden, daher könnten ohne sorgfältigen Entwurf Probleme mit der Abwärts- oder Aufwärtskompatibilität entstehen.
Fähigkeiten: Microservices sind hoch verteilte Systeme. Beurteilen Sie sehr genau, ob das Team über die notwendige Kompetenz und Erfahrung verfügt, erfolgreiche Arbeit zu leisten.
Bewährte Methoden
Modellieren Sie Dienste rund um die geschäftliche Domäne. Verwenden Sie DDD, um gebundene Kontexte zu identifizieren und klare Dienstgrenzen zu definieren. Vermeiden Sie die Erstellung von übermäßig präzisen Diensten, wodurch die Komplexität erhöht und die Leistung reduziert werden kann.
Dezentralisieren Sie alles. Jedes Team ist für die End-to-End-Gestaltung und Entwicklung von Diensten verantwortlich. Vermeiden Sie die gemeinsame Nutzung von Code oder Datenschemas.
Standardisieren Sie Ihre Technologieauswahl, indem Sie die Anzahl der von Ihnen verwendeten Sprachen und Frameworks einschränken. Richten Sie plattformweite Standards für Protokollierung, Überwachung und Bereitstellung ein.
Die Datenspeicherung sollte ausschließlich in dem Dienst erfolgen, der die Daten besitzt. Verwenden Sie den optimalen Speicher für jeden Dienst- und Datentyp.
Dienste kommunizieren über sorgfältig entworfene APIs. Vermeiden Sie die Weitergabe von Implementierungsdetails. APIs sollten die Domäne modellieren, nicht die interne Implementierung des Diensts.
Vermeiden Sie eine Kopplung zwischen Diensten. Kopplung kann durch gemeinsam genutzte Datenbankschemas oder starre Kommunikationsprotokolle entstehen.
Verbessern Sie die Sicherheit mithilfe der gegenseitigen Transport Layer Security (mTLS) für die Dienst-zu-Dienst-Verschlüsselung. Implementieren Sie rollenbasierte Zugriffssteuerung und verwenden Sie API-Gateways, um Richtlinien zu erzwingen.
Lagern Sie übergreifende Anliegen, wie die Authentifizierung und das Beenden von Secure Sockets Layer-Verbindungen, an das Gateway aus. Dienstgitter und Frameworks wie Dapr können auch bei häufigen cross-cutting-Bedenken wie mTLS-Authentifizierung und Resilienz helfen.
Informationen über die Domäne haben im Gateway nichts zu suchen. Das Gateway sollte Clientanforderungen ohne Kenntnis der Geschäftsregeln oder Domänenlogik verarbeiten und weiterleiten. Andernfalls wird das Gateway zu einer Abhängigkeit und kann zu Kopplung zwischen den Diensten führen.
Dienste sollten eine lose Kopplung und eine hohe funktionale Kohäsion aufweisen. Funktionen, die wahrscheinlich zusammen geändert werden, sollten auch zusammen gepackt und bereitgestellt werden. Wenn sie sich in separaten Diensten befinden, sind diese Dienste eng gekoppelt, da eine Änderung in einem Dienst eine Aktualisierung des anderen Diensts erfordert. Übermäßig geschwätzige Kommunikation zwischen zwei Diensten kann ein Symptom für enge Kopplung und geringer Zusammenhalt sein.
Verwenden Sie fortlaufende Integrations- und fortlaufende Bereitstellungspipelinen (CI/CD), um Tests und Bereitstellungen zu automatisieren. Stellen Sie Dienste unabhängig bereit und überwachen Sie die Rollout-Gesundheit.
Isolieren Sie Fehler. Nutzen Sie Resilienzstrategien, um zu verhindern, dass Fehler in einem Dienst kaskadieren. Weitere Informationen finden Sie unter Resilienzmuster und Entwerfen zuverlässiger Anwendungen.
Verwenden Sie Chaos Engineering, um die Resilienz Ihrer Microservice-Architektur und deren Abhängigkeiten zu testen. Bewerten und Verbessern der durch das System erfolgenden Behandlung von Teilfehlern.
Implementieren Sie zentralisierte Protokollierung, verteilte Ablaufverfolgung (OpenTelemetry) und metrikenauflistung, um die Observability zu gewährleisten.
Antimuster für Microservices
Wenn Sie Microservices entwerfen und implementieren, treten häufig spezifische Fallstricke auf, die die Vorteile dieses Architekturstils untergraben können. Das Erkennen dieser Antipattern hilft Teams, kostspielige Fehler zu vermeiden und stabilere, wartungsfähigere Systeme zu erstellen. Vermeiden Sie die folgenden Antipattern:
Die Implementierung von Microservices ohne ein tiefes Verständnis der Geschäftsdomäne führt zu schlecht ausgerichteten Dienstgrenzen und untergräbt die beabsichtigten Vorteile.
Das Entwerfen von Ereignissen, die von früheren oder zukünftigen Ereignissen abhängen, verstößt gegen das Prinzip der atomaren und eigenständigen Nachrichten. Diese Abhängigkeit zwingt die Verbraucher, zu warten und die Systemzulässigkeit zu reduzieren.
Die Verwendung von Datenbankentitäten als Ereignisse macht interne Dienstdetails verfügbar und vermittelt häufig nicht die richtige Geschäftsabsicht, was zu eng gekoppelten und unklaren Integrationen führt.
Das vollständige Vermeiden von Datenduplizierung um jeden Preis ist ein Antipattern. Die Verwendung von Mustern wie materialisierten Ansichten zur Verwaltung lokaler Kopien verbessert die Dienstautonomie und reduziert dienstübergreifende Abhängigkeiten.
Die Verwendung generischer Ereignisse zwingt Verbraucher, Nachrichten zu interpretieren und zu filtern. Dieser Ansatz erhöht unnötige Komplexität und reduziert klarheit in der ereignisgesteuerten Kommunikation.
Gemeinsame Bibliotheken oder Abhängigkeiten zwischen Mikroservices schaffen eine enge Kopplung, die Änderungen riskant und weit verbreitet macht und gegen das Prinzip der eigenständigen Dienste geht.
Das direkte Verfügbarmachen von Microservices für Verbraucher führt zu engen Kopplungs-, Skalierbarkeitsproblemen und Sicherheitsrisiken. Die Verwendung eines API-Gateways bietet einen sauberen, verwaltbaren und sicheren Einstiegspunkt.
Die Konfigurationswerte in Microservices werden eng mit bestimmten Umgebungen gekoppelt, wodurch Bereitstellungen schwieriger werden. Die Externalisierungskonfiguration fördert jedoch Flexibilität und Umgebungsübertragbarkeit.
Das Einbetten von Sicherheitslogik wie die Tokenüberprüfung direkt in Microservices erschwert ihren Code und die Wartung. Alternativ sorgt das Offloading der Sicherheit für dedizierte Komponenten dafür, dass Dienste fokussiert und sauberer sind.
Das Nichterfassen allgemeiner Microservices-Aufgaben führt zu sich wiederholendem, fehleranfälligem Code und begrenzt die Flexibilität. Alternativ vereinfacht die Verwendung von Abstraktionsframeworks wie Dapr die Entwicklung, indem Geschäftslogik von Infrastrukturbedenken entkoppelt wird.
Erstellen einer Microservices-Architektur
Die folgenden Artikel stellen einen strukturierten Ansatz für das Entwerfen, Erstellen und Betreiben einer Microservices-Architektur dar.
Domänenanalyse verwenden: Um häufige Fallstricke beim Entwerfen von Microservices zu vermeiden, verwenden Sie die Domänenanalyse, um Ihre Microservice-Grenzen zu definieren. Führen Sie die folgenden Schritte aus:
- Verwenden der Domänenanalyse zur Modellierung von Microservices
- Entwerfen von Microservices im Rahmen der taktischen DDD-Phase
- Identifizieren von Microservice-Grenzen
Entwerfen Sie die Dienste: Microservices erfordern einen dezentralen und agilen Ansatz zum Entwerfen und Erstellen von Anwendungen. Weitere Informationen finden Sie unter Entwerfen einer Microservices-Architektur.
Arbeiten in der Produktion: Da Microservices-Architekturen verteilt sind, müssen Sie über robuste Vorgänge für die Bereitstellung und Überwachung verfügen.