Architekturentwurf für Microservices

Azure DevOps

Microservices sind ein beliebtes Architekturkonzept für die Erstellung robuster, hochgradig skalierbarer, unabhängig bereitstellbarer Anwendungen, die sich schnell weiterentwickeln lassen. Eine erfolgreiche Microservices-Architektur erfordert jedoch eine andere Herangehensweise an das Entwerfen und Erstellen von Anwendungen.

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.

Logisches Diagramm der Microservicearchitektur.

Was sind Microservices?

  • Microservices sind klein, unabhängig und lose gekoppelt. Ein Dienst kann von einem kleinen Entwicklerteam geschrieben und verwaltet werden.

  • Jeder Dienst stellt eine separate Codebasis dar, die von einem kleinen Entwicklungsteam verwaltet werden kann.

  • Die Dienste können unabhängig voneinander bereitgestellt werden. Ein Team kann einen vorhandenen Dienst aktualisieren, ohne die gesamte Anwendung neu erstellen und erneut bereitstellen zu müssen.

  • Die Dienste sind dafür zuständig, ihre eigenen Daten und ihren externen Zustand beizubehalten. Dies ist ein Unterschied zum herkömmlichen Modell, in dem eine separate Datenschicht die Datenpersistenz verwaltet.

  • Dienste kommunizieren über klar definierte APIs miteinander. Die internen Implementierungsdetails jedes Diensts werden für andere Dienste verborgen.

  • Sie unterstützen die Programmierung in mehreren Sprachen. Dienste müssen beispielsweise nicht den gleichen Technologiestapel, die gleichen Bibliotheken oder die gleichen Frameworks verwenden.

Abgesehen von den Diensten selbst gibt es in einer typischen Architektur für Microservices noch einige weitere Komponenten:

Verwaltung/Orchestrierung. Diese Komponente ist dafür zuständig, Dienste auf Knoten zu platzieren, Fehler zu ermitteln, die Dienste auf Knoten zu verteilen usw. In der Regel handelt es sich bei dieser Komponente nicht um eine benutzerdefinierte, sondern um eine handelsübliche Technologie (z. B. Kubernetes).

API-Gateway. Das API-Gateway ist der Einstiegspunkt für Clients. Statt die Dienste direkt aufzurufen, rufen Clients das API-Gateway auf, das den Aufruf an die geeigneten Dienste im Back-End weiterleitet.

Ein API-Gateway bietet u. a. folgende Vorteile:

  • Es entkoppelt die Clients von den Diensten. Für Dienste kann eine Versionierung oder Umgestaltung durchgeführt werden, ohne dass sämtliche Clients aktualisiert werden müssen.

  • Dienste können nicht webfähige Messagingprotokolle verwenden, z.B. AMQP.

  • Das API-Gateway kann weitere übergreifende Funktionen ausführen, beispielsweise Authentifizierung, Protokollierung, SSL-Terminierung und Lastenausgleich.

  • Vordefinierte Richtlinien, etwa für Drosselung, Zwischenspeicherung, Transformation oder Prüfung.

Vorteile

  • Flexibilität: Die unabhängige Bereitstellung von Microservices vereinfacht die Verwaltung von Fehlerkorrekturen und Featureveröffentlichungen. Sie können einen Dienst aktualisieren, ohne die gesamte Anwendung erneut bereitstellen zu müssen, und im Problemfall einen Rollback für ein Update ausführen. In vielen herkömmlichen Anwendungen kann der gesamte Releaseprozess blockiert werden, wenn in einem Teil der Anwendung ein Fehler gefunden wird. Neue Features können sich verzögern, bis eine Fehlerbehebung integriert, getestet und veröffentlicht wurde.

  • Kleine, fokussierte Teams: Ein Microservice muss so kompakt sein, dass er von einem einzelnen Featureteam erstellt, getestet und bereitgestellt werden kann. Kleinere Teams sind agiler. Große Teams sind in der Regel weniger produktiv, da die Kommunikation langsamer ist, der Verwaltungsaufwand steigt und die Agilität abnimmt.

  • Kleine Codebasis. In einer monolithischen Anwendung werden Codeabhängigkeiten im Laufe der Zeit häufig unübersichtlich. Zum Hinzufügen eines neuen Features muss an vielen Stellen der Code bearbeitet werden. Da sich Microservices keinen Code und keine Datenspeicher teilen, enthält eine Microservices-Architektur weniger Abhängigkeiten und vereinfacht dadurch das Hinzufügen neuer Features.

  • Kombination verschiedener Technologien: Teams können sich für die Technologie entscheiden, die am besten zu ihrem Dienst passt, und eine Kombination aus geeigneten Technologiestapeln verwenden.

  • Fehlerisolation. Der Ausfall eines einzelnen Microservice hat nicht den Ausfall der gesamten Anwendung zur Folge – vorausgesetzt, die Upstream-Microservices sind für eine korrekte Behandlung von Ausfällen konzipiert. Sie können z. B. das Circuit Breaker-Muster (Trennschalter) implementieren oder Ihre Lösung so entwerfen, dass die Microservices miteinander kommunizieren, indem Sie asynchrone Messagingmuster verwenden.

  • Skalierbarkeit. Dienste können unabhängig skaliert werden. Dadurch lassen sich Subsysteme, die mehr Ressourcen benötigen, aufskalieren, ohne die gesamte Anwendung aufzuskalieren. Mit einem Orchestrator wie Kubernetes können Sie eine höhere Dichte von Diensten auf einem einzigen Host unterbringen, was eine effizientere Nutzung der Ressourcen ermöglicht.

  • Datenisolation: Schemaaktualisierungen sind wesentlich einfacher, da nur ein einzelner Microservice betroffen ist. Bei einer monolithischen Anwendung können sich Schemaaktualisierungen als echte Herausforderung erweisen, da verschiedene Teile der Anwendung unter Umständen die gleichen Daten nutzen, was jegliche Anpassung des Schemas zu einer riskanten Angelegenheit macht.

Herausforderungen

Die Vorteile von Microservices gibt es jedoch nicht umsonst. Im Anschluss finden Sie einige der Herausforderungen, die Sie vor der Erstellung einer Microservices-Architektur berücksichtigen sollten.

  • Komplexität. Eine Microserviceanwendung 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.

  • Entwicklung und Tests. Das Schreiben eines kleinen Diensts, der auf andere abhängige Dienste angewiesen ist, erfordert eine andere Herangehensweise als das Schreiben einer herkömmlichen monolithischen oder mehrschichtigen Anwendung. Vorhandene Tools sind nicht immer für die Arbeit mit Dienstabhängigkeiten geeignet. Refactoring über Dienstgrenzen hinweg kann schwierig sein. Das Testen von Dienstabhängigkeiten kann ebenfalls eine Herausforderung darstellen, insbesondere dann, wenn sich die Anwendung schnell weiterentwickelt.

  • Unzureichende Governance. Der dezentralisierte Ansatz für die Erstellung von Microservices bietet einige Vorteile, kann jedoch 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. Dies gilt insbesondere für übergreifende Funktionen wie die Protokollierung.

  • Netzwerkkonflikte und -latenz. Die Verwendung vieler kleiner, genau abgestimmter Dienste kann zu einer vermehrten Kommunikation zwischen den Diensten führen. Wenn die Kette der Dienstabhängigkeiten zu lang wird (Dienst A ruft B auf, der wiederum C aufruft...), kann die zusätzliche Latenz zu einem Problem werden. Beim Entwurf der APIs sollten Sie größte Umsicht walten lassen. Vermeiden Sie überladene APIs, denken Sie über Serialisierungsformate nach, und suchen Sie nach Stellen, an denen Sie asynchrone Kommunikationsmuster (etwa Warteschlangenbasierter Lastenausgleich) verwenden können.

  • Datenintegrität. Jeder Microservice ist für die eigene Datenpersistenz zuständig. Dadurch kann die Sicherstellung der Datenkonsistenz zu einer Herausforderung werden. Implementieren Sie die letztliche Konsistenz, wo immer möglich.

  • Verwaltung. Für den erfolgreichen Einsatz von Microservices ist eine ausgereifte DevOps-Kultur erforderlich. 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. Dienstupdates dürfen nicht zu Unterbrechungen bei abhängigen Diensten führen. 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 Systeme mit einem hohen Maß an Verteilung. Beurteilen Sie sehr genau, ob das Team über die notwendige Kompetenz und Erfahrung verfügt, erfolgreiche Arbeit zu leisten.

Prozess zum Erstellen einer Microservices-Architektur

In den hier aufgeführten Artikeln wird ein Strukturierungskonzept zum Entwerfen, Erstellen und Betreiben einer Microservicearchitektur vorgestellt.

Domänenanalyse. Nutzen Sie die Domänenanalyse, um Ihre Microservice-Grenzen zu definieren und häufige Probleme zu vermeiden. Folgen Sie diesen Schritten:

  1. Verwenden der Domänenanalyse zur Modellierung von Microservices
  2. Entwerfen von Microservices im Rahmen der taktischen DDD-Phase
  3. Identifizieren von Microservice-Grenzen

Entwerfen der Dienste Für Microservices ist in Bezug auf das Entwerfen und Erstellen von Anwendungen ein anderer Ansatz erforderlich. Weitere Informationen finden Sie unter Entwerfen einer Microservices-Architektur.

Betrieb in der Produktion. Microservices-Architekturen sind verteilt, daher benötigen Sie zuverlässige Vorgänge für die Bereitstellung und Überwachung.

Referenzarchitekturen für Microservices für Azure