Microservices – der aktuelle Architektur-Ansatz

by | 21.01.2019 | Wissen

Microservices haben sich vom Newcomer im Architektur-Bereich zum Platzhirsch entwickelt. Aber wie jeder andere Architektur-Ansatz sind auch Microservices ein Trade-Off und lösen daher nur spezifische Probleme.

Was ist und kann ein Microservice?

Bei der Definition von Microservices gibt es unterschiedliche Sichtweisen. ISA (Independent System Architecture) beschreibt Microservices als eine andere Art von Modulen. Während in klassischen Systemen Module mit Hilfe von Programmiersprachen-Features umgesetzt werden, sind Microservices getrennte Prozesse oder besser noch getrennte virtuelle Maschinen. Mittlerweile sind Microservice meistens Docker Container, eine leichtgewichtige Alternative zu virtuellen Maschinen. Die Kommunikation erfolgt über das Netzwerk beispielsweise per REST. So sind Microservices viel stärker voneinander entkoppelt als dies bei Modulen in einem Deployment-Monolithen möglich wäre. Beispielsweise kann jeder Microservice in einer anderen Programmiersprache entwickelt werden. Wenn ein Microservice abstürzt, laufen die anderen weiter, während bei einem Deployment Monolithen üblicherweise der gesamte Monolith abstürzt. Wenn man diese Eigenschaft geschickt ausnutzt, kann man deutlich robustere Systeme entwickeln.

Eine weitere sehr wichtige Eigenschaft ist das getrennte Deployment. Eine neue Version eines Microservice kann getrennt von allen anderen Microservices in Produktion gebracht werden. Dadurch ist es möglich, ein neues Feature in einem Microservice zu implementieren und in Produktion zu bringen, ohne dass es Auswirkungen auf die anderen Microservices hat.

Self-contained Systems (SCS) sind ein Sonderfall von Microservices: Sie enthalten neben Logik und Persistenz eine Web-UI. So kann ein Feature in einem einzigen SCS umgesetzt werden, selbst wenn das Feature die UI, Logik und Persistenz umfasst. Die meisten fachlichen Änderungen ziehen sich durch alle diese Schichten.

Hierarchie

Um ein System umzusetzen, kann man es hierachisch zerlegen.

Hierarchische Darstellung von Microservices

Die Abbildung zeigt:

  • Auf der obersten Ebene wird ein System von mehreren Teams entwickelt. Scrum schlägt für die Größe der Teams 5-8 Personen vor.
  • Jedes dieser Teams sollte eine unabhängige Fachlichkeit bearbeiten. Dazu haben sich Bounded Contexts aus dem Domain-driven Design bewährt. Jeder Bounded Context hat ein eigenes Domänenmodell. In einer E-Commerce-Anwendung könnte es ein Domänenmodell für die Rechnungslegung mit Steuersätzen, Preisen und Rechnungsadressen geben. Davon getrennt kann es ein Domänenmodell für das Ausliefern der Bestellungen geben. Dort sind Paketdienstleister, Lieferadressen und Größe und Gewicht der Waren relevant.
  • Technisch können die Bounded Contexts als ein oder mehrere Microservices umgesetzt werden. Dabei spielen technische Gründe eine Rolle: Wenn bei der Rechnungslegung die Bezahlung besonders aufwändig ist, weil sie externe Dienstleister nutzt, kann sie in einen eigenen Microservice ausgelagert werden und so getrennt skaliert werden.

Auf technischer Ebene müssen trotz der weitgehenden Unabhängigkeit dennoch einige Entscheidungen getroffen werden, die alle Microservices betreffen. Man spricht von der Makro-Architektur im Gegensatz zur Mikro-Architektur, die Entscheidungen spezifisch für einen Microservice umfasst. Typische Makro-Architektur-Entscheidungen betreffen die Kommunikation von Microservices über REST oder Messaging-Systeme oder Standards für den Betrieb der Microservices.

Vorteile

Dieser Architektur-Ansatz hat verschiedene Vorteile:

  • Die Teams können weitgehend unabhängig voneinander arbeiten. Technische Entscheidungen können im Team getroffen werden. Selbst den Einsatz einer anderen Programmiersprache oder eines anderen Frameworks kann jedes Team selbst entscheiden. Natürlich ist es auch möglich, Standards vorzugeben. Da auch die Fachlichkeiten durch die Bounded Contexts voneinander entkoppelt sind, können fachliche und technische Änderungen in den meisten Fällen von einem Team umgesetzt werden, ohne dass die anderen Teams beeinflusst werden. So macht die Microservices-Architektur aus einem großen Projekt mehrere kleinere Projekte. So unterstützen Microservices auch die Skalierung agiler Prozesse.
  • Da Microservices getrennt deployt werden können, ist es viel einfacher, Continuous Delivery damit umzusetzen. Der State of DevOps Report zeigt, dass in der Praxis durch mehrmaliges Deployment pro Tag nicht nur das Time-to-Marekt für neue Features sinkt, sondern Deployments mit einer höheren Wahrscheinlichkeit problemlos durchgeführt werden können, Systeme bei einem Ausfall schneller wieder online sind und mehr Zeit für die Entwicklung neuer Features aufgewendet werden kann. Mehrmals pro Tag zu deployen ist aber oft nur durch das unabhängige Deployment kleiner Microservices umsetzbar.
  • Bei der Ablösung eines Legacy Systems kann ein Teil der Funktionalität in einem Microservice neu implementiert werden. So ist man nicht an die technischen Entscheidungen im Legacy System gebunden. Die neuen Microservices nutzen zur Integration Schnittstellen zum Legacy System. So sind die Microservices unabhängig von der internen Struktur des Legacy Systems, die oft viel zu komplex ist.  Die Migration eines Legacy Systems (beispielsweise um eine höhere Deployment-Geschwindigkeit zu erreichen) ist das häufigste Szenario für den Einsatz von Microservices.
  • Microservices versprechen eine nachhaltige Entwicklung. In vielen Systemen wird zwar am Anfang eine klare Architektur definiert, aber mit der Zeit werden immer mehr neue Abhängigkeiten zwischen den Modulen eingeführt und so die Architektur kompromittiert. Das passiert oft unabsichtlich. Microservices exponieren Schnittstellen zum Beispiel mit REST. Eine neue Abhängigkeit zu einer solchen Schnittstelle schleicht sich nicht einfach ein, sondern muss ausprogrammiert werden. Dadurch ist das Risiko für einen Verfall der Architektur geringer. Außerdem kann jeder Microservice isoliert neu geschrieben werden. In einem Deployment Monolithen kann eigentlich nur das gesamte System abgelöst werden. Ein neu geschriebener Microservice kann auf anderen Technologien basieren und muss von dem alten Code nichts weiterverwenden. Das erlaubt einen kleinen Neuanfang. Diese Technologie-Unabhängigkeit erlaubt es auch, ein System einfacher auf eine neue Technologie-Version zu bringen: Man kann die neue Version für jeden Microservice getrennt einführen. Das verringert das Risiko und erlaubt es sogar, einige der Microservices gar nicht zu aktualisieren. Das erleichtert den Umgang mit dem technischen Fortschritt erheblich.

Neben diesen Vorteilen bieten Microservices eine einfachere Skalierbarkeit, weil nur einzelne Microservices skaliert werden müssen. Sie können wie schon erwähnt robuster sein und sie können sicherer sein, weil beispielsweise die Kommunikation zwischen Microservices mit Firewalls abgesichert werden kann. Also muss man nicht unbedingt ein großes komplexes Projekt bearbeiten, um von Microservices zu profitieren.

Herausforderungen

Wie alle Architektur-Ansätze sind auch Microservices ein Trade-Off. Ein offensichtlicher Nachteil ist, dass durch die größere Anzahl der deploybaren Artefakte die Aufwände im Betrieb steigen – schließlich müssen alle diese Artefakte überwacht werden. Das ist aber ein dankbarer Markt, den zahlreiche Technologien besetzen, sodass es immer einfacher wird, auch große Microservices-Systeme zu betreiben. Dazu zählen Docker und Kubernetes als Container-Umgebungen.

Eine Architektur, bei der jede Änderung mehrere Microservices betrifft, ist problematisch: Vorteile wie die entkoppelte Entwicklung lassen sich dann nicht nutzen. Im Gegensatz zu einem Deployment Monolithen muss man außerdem das Deployment mehrerer Microservices koordinieren. Deswegen ist der fachliche Schnitt so wichtig. Und natürlich hilft es, dass Microservice-Architekturen nicht so einfach verfallen. Es erscheint aber kaum sinnvoll, eine Entscheidung gegen Microservices zu treffen, weil man davon ausgeht, dass man keinen ausreichend guten fachlichen Schnitt finden kann.

Fazit

Microservices sind eine gute architekturelle Antwort auf die Herausforderungen agiler Software-Entwicklung und von Continuous Deployment, haben aber auch weitere technische Vorteile. Am Ende stehen sie für eine andere Art von Modularisierung und ändern somit einen fundamentalen Parameter in der Software-Entwicklung. Für einen tieferen Einstieg bietet sich das Microservices-Buch oder der kostenlose Microservices-Überblick an. Technische Lösungen für die Herausforderungen der Microservices betrachtet das Microservices-Praxisbuch  oder die kostenlosen Microservices-Rezepte.