Ist eine Microservice-Architektur Stand der Technik? (Teil 2 - Vor- und Nachteile)

Microservices haben zwar jede Menge Vorteile, aber auch viele Nachteile. Nur wenn die Vorteile die Nachteile überwiegen, macht der Einsatz einer Microservice-Architektur Sinn. Nur wenn die Verhältnismäßigkeit zwischen Vor- und Nachteilen besser ist als bei alternativen Architekturen, gilt eine Microservice-Architektur als fortschrittlicher. Dies ist aber Voraussetzung für den Stand der Technik, und dieser üblicherweise Vertragsbestandteil oder gewöhnlich vorausgesetzte Eigenschaft. Eine Microservice-Architektur ist somit nur dann vertragskonform, wenn sich ihre Fortschrittlichkeit für das jeweilige Projekt nachweisen lässt.

Im letzten Blogpost wurde dargelegt, dass Microservice-Architekturen generell zwei der drei Bedingungen für den Stand der Technik erfüllen. Diesmal geht es darum zu prüfen, welche Vor- und Nachteile eine Microservice-Architektur gegenüber einem Modulithen1 - der typischen Alternative zu einer Microservice-Architektur - haben. Dazu lässt sich viel z.B. im Internet oder in der Literatur finden. Hier eine Liste der typischerweise genannten (Diskussion darüber bzw. zu weiteren Vor- und Nachteilen gerne in den Kommentaren):

Vorteile einer Microservice-Architektur gegenüber einem Modulithen:

  1. Unterschiedliche Skalierung: Möglichkeit, einzelne Teile unabhängig von anderen zu monitoren und bei Bedarf flexibel auf unterschiedlichen Nodes zu skalieren.
  2. Unabhängigkeit: einzelne Teile können unabhängig von anderen entwickelt, gewartet und getestet werden. Dabei können unterschiedliche Sprachen, Tools, Technologien und Versionen je Service verwendet werden. Updates und Veränderungen der verwendeten Technologien können inkrementell gemacht werden.
  3. Codierungsproduktivität: Der Code kann auf Grund der Unabhängigkeit paralleler, verteilter und rascher als bei voneinander abhängigen Modulen entwickelt werden.
  4. Testproduktivität von Komponententests: Komponententests benötigen kein Gesamtsystem und können somit produktiver durchgeführt werden.
  5. Deployment einzelner Teile: raschere und von anderen unabhängige Deployments einzelner Microservices ohne Standzeiten des Gesamtsystems möglich.
  6. Gesichertere Architektur: Da die architekturellen Komponenten durch die Aufteilung in Microservices ersichtlich ist und nicht umgangen werden kann.

Nachteile einer Microservice-Architektur gegenüber einem Modulithen:

  1. Performance: geringere Performance, da die Kommunikation zwischen Services um ein Vielfaches latenter und langsamer ist, als die Kommunikation zwischen Modulen eines Modulithen. Insbesondere die Aggregation von Microservice-übergreifenden Daten ist nicht nur extrem komplex, sondern auch unperformant.
  2. Organisationsaufwand: Die Gesamtarchitektur, sowie Updates und Schnittstellen müssen teamübergreifend koordiniert werden. Wildwuchs an Sprachen, Tools, Technologien und Versionen, aber auch UI-, Protokollierungs-, Reporting- oder Überwachungsstandards muss verhindert werden.
  3. Entwicklungsproduktivität: Unterschiedliche Teams, Lösungsansätze und Codebasen, aber auch Kommunikationscode und die Vermeidung von Domain-Reuse führen zu insgesamt deutlich mehr Code, unterschiedliche Stacks und geringer fokussiertem KnowHow. Viele teilweise komplexe Patterns müssen eingesetzt werden, um Dinge zu realisieren, die bei Modulithen keinen oder nur trivialen Code benötigen.2
  4. Testproduktivität übergreifender Testarten: Alle komponentenübergreifenden Testarten (Systemtests, End-to-End-Tests, Integrationstests, Akzeptanztests etc.) benötigen ein aufwändiges und auf Entwickler/Testrechnern oft nicht bereitstellbares Testsystem.
  5. Deployment des Gesamtsystems: komplexeres Deployment des Gesamtsystems.
  6. Starre Architektur: Da eine Änderung der Architektur (z.B. Verschieben von Daten oder Services in andere Microservices oder Kontexte) ungleich aufwändiger ist als bei einem Modulithen.
  7. Inkonsistenz: Bei der Verteilung der Daten kann es zu Inkonsistenzen kommen, die nur durch komplexe Patterns und Technologien, oft auch nur auf eventuelle Konsistenz gebracht werden können.
  8. Infrastrukturkosten: Für jedes Microservice können eigene Kosten für Testsuite, Deployment-Playbooks, Hosting-Infrastruktur, Überwachungstools und mehr anfallen.
  9. Debuggingaufwand: Höherer Aufwand, da Debugging Microservice- und auch of Stack- und programmiersprachenübergreifend enorm aufwändig, teils unmöglich ist.

Nicht betrachtet wurden hier Vor- oder Nachteile, die auf Grund von schlechter Umsetzung der jeweiligen Architektur entstehen. Enge Kopplung zwischen Microservices bzw. Modulen und geringe Kohesion innerhalb dieser ist beispielsweise immer schlecht. Um das zu vermeiden, muss bei einer Microservice-Architektur einerseits eine geeignete Aufteilung der Fachlichkeit in unterschiedliche Kontexte gefunden werden. Andererseits muss auch das Fachmodell auf die Microservices aufgeteilt werden bzw. unterschiedliche fachliche Sichten je Microservice auf dieselben Fachklassen existieren. Microservices sollten daher auch so gut wie nie Zugriff auf ihre Fachklassen bieten, und auch andere nicht von diesbezüglichen Zustandsänderungen benachrichtigen müssen.3

Es scheint, als ob die Anzahl der Nachteile einer Microservice-Architektur gegenüber einem Modulithen die Anzahl der Vorteile überwiegen würde. Aber nicht die Anzahl, sondern deren Auswirkungen auf das jeweilige Projekt sind relevant. Im nächsten Blogpost werden daher die Vorteile den Nachteilen gegenübergestellt und dann Voraussetzungen von Softwareprojekten ausgearbeitet, die gegeben sein müssen, damit eine Microservice-Architektur für die Software als Stand der Technik angesehen werden kann.

Fazit: Eine Microservice-Architektur hat nicht nur Vorteile, sondern auch gewichtige Nachteile. Es scheint nicht leicht zu sein, Situationen zu finden, wo die Vorteile die Nachteile überwiegen bzw. in Summe ein besseres Verhältnis als bei einer modulithischen Architektur haben.

___

1. Mit dem Aufkommen von Web- und Microservices haben Monolithen den Stempel einer unwartbaren, riesigen, Big-Ball-of-Mud Architektur aufgedrückt bekommen. Darum verwenden wir den Begriff "Modulith" (= ein gut strukturierter Monolith = das was immer das Ziel einer monolithischen Architektur war), um klarzumachen, dass wir die Microstervice-Architektur nicht mit einer schlecht gelungenen Umsetzung einer ansonsten vielleicht guten Architektur vergleichen. 

2. beispielsweise Outbox Pattern statt getter oder trivialem Event-Handling 

3. Das genannte Outbox Pattern ist aber genau dafür da, um andere von Zustandsänderungen innerhalb eines Microservices zu benachrichtigen. Die Verwendung dieses Patterns ist also ein Hinweis darauf, dass hier u.U. die Kontektgrenzen falsch gezogen wurden. 

Kommentare

CC BY-NC-SA 3.0 AT Sebastian Dietrich, e-movimento