Veröffentlicht am 22. Mai 2016 von Nicola Rizhikov
Alle sprechen über Microservices als bevorzugten Ansatz zur Strukturierung komplexer Informationssysteme.
Hier sind einige gängige Argumente:
- Unsere monolithische Anwendung wurde zu groß und komplex, daher werden wir sie in Services aufteilen
- Wir haben die Leistungsgrenze unseres Monolithen erreicht und hoffen, diese durch die Aufteilung in Services zu überwinden
- Unser System wird sehr groß werden, daher starten wir mit einer Microservices-Architektur, um zukünftig skalieren zu können
- Erfolgreiche Unternehmen setzen auf Microservices – wir möchten einfach die Best Practices der Branche anwenden
Aus meiner Sicht haben diese Motivationen keinen direkten Bezug zu diesem Architekturmuster und können Sie in echte Schwierigkeiten oder Verschwendung führen. Die Entscheidung für einen Microservices-Architekturstil sollte bewusst und mit vollem Verständnis aller Konsequenzen und Abwägungen getroffen werden.
Lassen Sie uns einige ernsthafte Nachteile aufzählen, die Sie bei Microservices in Kauf nehmen müssen:
Konsistenz und Abhängigkeitsverwaltung
Wenn Sie Ihr System in unabhängig voneinander weiterentwickelte Services aufteilen, bestehen zwischen diesen Teilen weiterhin logische Abhängigkeiten, und das System als Ganzes muss konsistent bleiben. In einer monolithischen Anwendung sind diese Abhängigkeiten explizit im Code fest verankert. Bei der Aufteilung in einzelne Teile werden Abhängigkeiten jedoch „implizit", und Sie benötigen zusätzlichen Aufwand (Versionen, Verträge, Tests usw.), um sicherzustellen, dass sie erfüllt sind. Ihr System wird fragiler und unvorhersehbarer. Dies ähnelt in gewisser Weise der Wahl zwischen ACID und BASE. Im ACID-Fall gibt es zu jedem Zeitpunkt nur eine einzige zuverlässige Version der Welt; in der BASE-Welt können viele parallele Galaxien nebeneinander existieren, und Sie müssen die Konsistenz manuell sicherstellen. Im schlimmsten Fall könnten Sie beim bekannten Problem der Abhängigkeitshölle landen. Ohne solide Kenntnisse und Werkzeuge im Bereich „Abhängigkeitsverwaltung" befinden Sie sich auf einem gefährlichen Weg.
Die „richtige" Dekomposition
Das größte Herausforderung beim Microservices-Ansatz (und im Programmieren generell :) – wie zerlegt man das Ganze in Teile? Wie viele erfahrene Architekten wissen, ist die anfängliche Dekomposition fast immer falsch. Das „richtig" zu machen bedeutet, die Zukunft vorhersagen zu können. Anstatt auf theoretische Hinweise zu verweisen, lassen Sie uns die Konsequenzen einer „falschen" Dekomposition besprechen.
Querschnittsfunktionalität: Es ist leicht, eine neue Feature-Anforderung zu erhalten, die Änderungen in vielen Services erfordert und dann konsistent ausgeliefert werden muss. Manchmal würde dieses Feature im Monolithen Minuten dauern und in einer Microservices-Umgebung Stunden oder Tage. Dasselbe gilt für querschnittliche Fehler.
Rekomposition – wenn Sie einen besseren Weg gefunden haben, Ihr System zu strukturieren, müssen Sie Ihre Architektur neu zusammenstellen. Im Monolithen ist das einfaches und bekanntes „Refactoring", das relativ sicher durchgeführt werden kann. Bei Microservices ist eine solche Transformation in vielen Fällen keine triviale Aufgabe.
Betriebliche Kosten
Dies ist eine relativ bekannte Belastung – jede neue Komponente bringt auf nicht-lineare Weise betrieblichen Mehraufwand mit sich. Verteilte Systeme erfordern eine qualitativ weitaus komplexere Infrastruktur sowie Werkzeuge und Experten, um einen zuverlässigen Betrieb zu gewährleisten.
Vorteile von Microservices
Das richtige Wachstum Ihres Unternehmens und Systems ist nicht einfach. Sie müssen zwei miteinander verknüpfte Einheiten verwalten – die Organisation und das System. Das wichtigste Argument für Microservices ist für mich die Ausrichtung beider im Einklang mit dem Conwayschen Gesetz. (Micro)Services ermöglichen es, einen Service an bereichsübergreifende Teamgrenzen anzupassen – und Teams so weit wie möglich unabhängig zu machen. Die entscheidende Einschränkung, die Sie nicht übersehen sollten, ist, dass das Team in der Lage sein muss, mit minimalem Überschneidungen und Konflikten mit anderen Teams „echten Mehrwert" für den Endnutzer zu konzipieren, entwickeln und bereitstellen. „System und Organisation skalieren" ist ein lohnendes Ziel, für das man den Preis von Microservices zahlen kann. Die einfache Formel lautet:
- ein Team → viele Services → falsch (Mehraufwand)
- viele Teams → ein Service → falsch (Konflikte)
- ein Team → ein Service → richtig
Unter diesen Bedingungen sollte die Größe des Services nicht „zu mikro" sein, sondern ausschließlich durch die Größe und die Fähigkeiten Ihrer Teams definiert werden. Wie wir wissen, kann ein Team nur in einem sehr begrenzten Intervall skalieren – 2–7 Personen – aber die Fähigkeiten können um ein paar Größenordnungen variieren.
Ein weiteres valides Argument für mich ist der „Technologiewechsel" – eine Situation, in der Ihre aktuelle Technologie die erforderlichen technischen Eigenschaften, beispielsweise die Performance, nicht mehr liefern kann und Sie einen kritischen Teil Ihres Systems „in C schreiben" müssen.
Fazit
Diese Herausforderungen und ihre Ableitungen werden zu Beginn den Großteil Ihrer Zeit in Anspruch nehmen und Sie in kritischen Phasen erheblich verlangsamen. Deshalb klingt der Ansatz „Microservices zuerst" für mich sehr verdächtig. Die meisten erfolgreichen „Microservices"-Anwendungen entstanden als Überarbeitung von Monolithen in der Produktion hin zu einzelnen Teilen. In diesen Fällen verfügten die Entwickler über ein tiefes Verständnis der internen Systemstrukturen und Probleme.
In den meisten Fällen plädiere ich für „Monolith zuerst".







