Community

Microservices. Patterns und Antipatterns

: Stefan Tilkov hat bei der Java User Group Hessen das Hypethema Microservices unter die Lupe genommen und die Vorteile praxisnah von den Nachteilen getrennt.

Microservices sind ein Hypethema. Anders als bei Blockchain schlägt ihnen allerdings nur wenig Skepsis entgegen. Stefan Tilkov hat sich deshalb mal daran gemacht, für uns die Spreu vom Weizen zu trennen.

Microservices sind ein Architekturmuster, das darauf ausgerichtet ist, dass die verschiedenen Module einer Software als separate operative Einheiten einzeln deploybar und austauschbar sind. Die Idee der Modularisierung ist nicht neu, erste urkundliche Erwähnung fand sie schon 1972 in einem Papier von David Parnas, der sich schon damals als Pionier der objektorientierten Programmierung einen Namen gemacht hat.

Patterns

Neu ist aber, wie die Modularisierung dank des technischen Fortschritts heute umgesetzt werden kann – nämlich, indem man sie a.) von einem technischen Detail der Deploymentarchitektur zu einem durchgängigen Designprinzip der gesamten Software erklärt und b.) die gesamte Netzwerkkommunikation über programmiersprachenunabhängige Schnittstellen abwickelt und so die Verkapselung der einzelnen Artefakte praktisch erzwingt.

Daraus ergeben sich, so die Argumentation der Microservices-Befürworter, ganz entscheidende Vorteile in den Punkten Isolation, Autonomie, Skalierbarkeit, Belastbarkeit, Schnelligkeit, Flexibilität und Austauschbarkeit. Insbesondere letztere ist eine Abkehr von alten Glaubenssätzen, die der Wiederverwertbarkeit von Softwareteilen in der Vordergrund stellte, nicht ihre Ersetzbarkeit. Dahinter steht die Idee, dass nichts so sehr aufgebläht werden sollte, dass man sich nicht auch wieder davon trennen könnte (vergleiche dazu auch den Leitsatz von James Lewis, Vordenker der Microservices: „Design for replaceability, not for reuse“). Denn das passiert leicht, wenn über Jahre nur in die Features einer Software statt in ihre Grundarchitektur investiert wird. Am Ende eines solchen Prozesses steht dann schlimmstenfalls ein 7-Millionen-Codezeilen-Monolith, der unmöglich zu modernisieren ist.

Pattern Evolutionäre Architektur

Nichts ist von Anfang an perfekt. Das gilt auch und insbesondere vor dem Hintergrund der Digitalisierung, die in einem bisher unbekannten Tempo immer neue technologische Lösungen hervorbringt. In diesem Umfeld ist der klassische deutsche Lösungsweg einer Perfektionierung am Reißbrett und anschließenden Umsetzung eines bei der Geburt schon perfekten Produktes völlig unbrauchbar. Denn wir wissen bereits heute, dass eine Software morgen schon von gestern sein kann, sofern man sie nicht permanent modernisiert.

Das Pattern der Evolutionären Architektur baut dieses Grundprinzip der permanenten, iterativen Verbesserung schon in den Bauplan der Software mit ein: Anstelle großer Monolithen treten kleine autarke Inseln, die minimalinvasiv weiterentwickelt oder ausgetauscht werden können, weil sie nur in minimalen Abhängigkeiten stehen. Das schafft zudem günstige Voraussetzung dafür, auch in Sachen Mikroarchitektur Neues auszuprobieren.

Antipatterns

Das zu den Vorteilen von Microservices. Aber gibt es auch Nachteile? Ja, durchaus, sagt Stefan Tilkov. Und zwar dann, wenn ein hochmodulares System nur so tut, als sei es hochmodular. Diese Gefahr besteht immer dann, wenn die Modularität nur für Teile der Applikation gilt und nicht konsequent für die komplette Anwendung. Ist das der Fall, können Entscheidungen weiterhin nur für das große Ganze getroffen werden, kann weiterhin nur das große Ganze in Betrieb genommen, weiterentwickelt, gewartet werden. Die Komplexität mindert sich nicht, sondern wird im schlimmsten Fall sogar gesteigert – wilder Technologiemix, schwer durchschaubarer Quellcode, massiver Netzwerküberbau. Und obwohl dies die Kosten einer Software eher steigert als senkt, kommt es vor, dass beide Prinzipien in ein und derselben IT-Lösung Anwendung finden, einfach, weil man dem Trend von Microservices folgen will und die Konsequenzen hybrider Systeme nicht bedenkt.

Antipattern Entkopplungsillusion

Eines der Kernprobleme von Microservices ist die Überschneidung wiederstreitender Interessen. So kann ein Stakeholder ein bestimmtes Feature für absolut geschäftskritisch halten, während ein anderer darin eher eine randständige oder gar überflüssige Funktion sieht – was zum Problem werden kann, wenn von diesen widerstreitenden Interessen ein und dasselbe Modul betroffen ist, weil die technische Teilung in einzelne Module nicht zu den Anforderungen der einzelnen Stakeholder passt. Die Folge sind paradoxe Anforderungen, hohe Abstimmungsaufwände und Verzögerungen durch Flaschenhälse bzw. Nadelöhre.

Antipattern Mikroplattform

Eine weitere Gefahr lauert in den so genannten Mikroplattformen, die häufig allen Microservices mitgegeben werden, um diese möglichst autark und unabhängig von ihrer Umgebung zu machen. Diese werden in dem Moment zum Nachteil, wenn beispielsweise auf die neue Version einer Bibliothek geupgradet und diese neue Version zur Laufzeit der Anwendung auf allen Mikroplattformen gleichzeitig eingespielt werden muss. In solchen Fällen geraten deren Unabhängigkeit und deren zentrale Administration in Widerspruch zueinander. Hier stellt sich grundsätzlich die Frage, ob die genutzten Microservices alle mit dem gleichen Technologiestack gebaut sein müssen oder ob nicht mehr Individualität erlaubt sein sollte bzw. sogar wünschenswert wäre.

Antipatterns Entity Service und Anemic Services

Als Entity Services werden funktionale Dienste bezeichnet, die von einzelnen oder mehreren Geschäftsprozessen abgeleitet sind. Beispiele sind etwa die Entitäten Bestellung, Kunde, Arbeitszeittabelle oder Rechnung. Als funktional abgegrenzte Einheiten sind sie eigentlich zur Verbesserung der Effizienz gedacht, weil sie von mehreren Nutzern gleichzeitig genutzt werden und mehrere Aufgaben gleichzeitig bewältigen können. In einer Microservices-Architektur werden sie allerdings zu Antipattern, weil die meisten von ihnen Aggregate aus mehreren Entitäten erfordern und die so entstehenden Abhängigkeiten der angestrebten Autarkie von Microservices zuwiderlaufen.

Anders aber ähnlich nachteilig können sich Anemic Services auswirken, die deshalb als „blutarm“ bezeichnet werden, weil sie aus Gründen der Wiederverwendbarkeit keinerlei Businesslogik enthalten und im Kontext von Microservices ungünstig sind, weil sie einen zu hohen Netzwerküberbau benötigen und überdies zu Flaschenhälsen und Performance-Problemen bei der Datenverarbeitung führen können.

Antipattern Wiederverwendung

Je generischer Funktionen sind, desto wiederverwertbarer sind sie. In der Welt der Microservices ist dies, wie eingangs schon erwähnt, kein Vorteil, sondern ein Nachteil, weil zu Allgemeines immer neu gecustomized werden muss und so der Code an unnötiger Komplexität zunimmt, statt diese abzubauen.

Organisatorische Antipatterns und Patterns

Auch organisatorische Antipatterns werden von Stefan Tilkov in seinem Vortrag berührt, zum Beispiel das Thema Interessenskonflikte und Entscheidungsgerangel zwischen den verschiedenen Stakeholdern einer Applikation. Als Gegenentwurf zu diesen strukturell begründeten Antipatterns empfiehlt Tilkov ein Pattern, den er „Autonome Zellen“ nennt, weil er die Stakeholder in kleine, gleichberechtigte, unabhängige und handlungsfähige Einheiten unterteilt, die sich gegenseitig nicht mehr in die Quere kommen können, flachere Hierarchien und kürzere Entscheidungswege aufweisen. Jede Zelle enthält dabei eine angemessene Anzahl von Vertretern aus Fachseite, Entwicklung und Betrieb.

Sizing Patterns

Und es gibt auch noch neutrale Patterns, zum Beispiel für das Sizing. Damit meint Tilkov die Konzepte Function as a Service (FaaS), das für Pricing Engines empfehlenswert ist, MicroSOA, das Produktdetailseiten von Onlineshops gute Dienste leistet oder Distributed Domain-driven Design (DDDD), wie es in logistischen Applikationen Anwendung findet.

User Interface

Und geschieht etwas in Tilkovs Vortrag nun etwas, das lange überfällig war und die Frontendentwickler freuen dürfte: Er weist noch einmal deutlich auf die Relevanz einer guten und durchdachten Frontendentwicklung hin – und das mit Nachdruck. Lange begegneten eingefleischte Backendentwickler dieser vergleichsweise jungen Disziplin mit Skepsis, stellenweise sogar mit „milder Verachtung“, unterstellend, dass nur das Backend den inneren Wert einer Software begründet, das Frontend aber als Sahne auf der Torte zweitrangig sei. Dabei ist ein intelligentes Frontend missionskritisch für den Erfolg und die Funktionsfähigkeit einer Software.

Antipattern Frontendmonolith

Ein monolithisches Frontend entsteht immer dann, wenn das Backend aus den o. g. Anemic Services besteht – ein absolutes Antipattern für Tilkov, weil das Frontend dann alles das leisten muss, was das Backend nicht leistet. Die Folge: Starke Abhängigkeiten von den gewählten Frameworks, Flaschenhälse/Nadelöhre bei der Entwicklung, komplizierte und zeitaufwendige Weiterentwicklung, Verlust der Modularität.

Wie es besser geht beschreibt Tilkov am Beispiel E-Commerce unter dem Stichwort Self-contained Systems (SCS), in denen Microservices geradezu idealtypisch angewendet werden. Diese in sich geschlossenen Systeme machen keinen Unterschied zwischen Frontend und Backend, sondern setzen idealerweise alles als Microservices um, inkl. Datenbank und User Interface. So sind die einzelnen Features maximal unabhängig, können Prozesse autonom durchführen, sind Leichtgewichte bei der Integration und benötigen keine extra Infrastruktur.

Pattern Monolith

Ja, richtig gelesen! Bis zu einer bestimmten Grenze an Codezeilen sind Monolithen durchaus sinnvoll, so Tilkov. Denn bis dahin sind sie einheitlich, straff integriert und können an einem Stück als Einheit deployt und maintaint werden. Bis dahin können sie auch wo nötig modularisiert werden, sind leicht zu refaktorieren und ihre technischen Entscheidungen sind homogen.

Warum also nicht einfach viele davon bauen? fragt Stefan Tilkov provokant und gibt folgende Empfehlungen zum Abschluss.

Fazit

Vorsicht vor dem Königsweg – es gibt ihn nicht. Auch wenn die Idee hinter Microservices in vielerlei Hinsicht sinnvoll ist und seine Kernmantras separate Deploybarkeit und programmiersprachenunabhängige Kommunikationsschnittstellen absolut überzeugend sind, bleibt der Kontext entscheidend: Priorisiere die Benefits, die du erwartest und suche dann die passenden Lösungen dafür aus.

Empfehlung der Redaktion: Zum Thema Microservices möchten wir Ihnen auch diesen JUGH-Vortrag empfehlen: Vom Monolithen zu Microservices – ein Erfahrungsbericht.

(jw)

Sebastian Hardt