
Die Einführung von Microservices hat sich in der modernen Softwarearchitektur als äußerst populäre Wahl etabliert. Viele Organisationen erhoffen sich davon eine gesteigerte Flexibilität, schnellere Entwicklungszyklen und eine bessere Skalierbarkeit. Der Gedanke, große Softwaresysteme in kleinere, unabhängige Dienste zu unterteilen, erscheint auf den ersten Blick verlockend und vielversprechend.
Doch diese Architekturform birgt auch erhebliche Fallstricke, die oft unterschätzt werden. Der Gewinn an Beweglichkeit wird teuer erkauft durch eine drastische Zunahme an Komplexität – sowohl auf technischer als auch auf organisatorischer Ebene. Wer sich für Microservices entscheidet, begibt sich auf einen Pfad, der wohlüberlegte Vorbereitung, Disziplin und eine klare strategische Ausrichtung verlangt.
In diesem Artikel möchte ich daher aufzeigen, welche Überlegungen und Herausforderungen beachtet werden sollten, um Microservices als tragfähige Lösung umzusetzen.
Kurze Wiederholung: Was sind Microservices?
Eine allgemein anerkannte Definition für Microservices gibt es nicht. Im Wesentlichen geht es darum, größere serverseitige Software-Systeme in kleinere Dienste aufzuteilen. Die optimale Größe eines Microservices ist umstritten, ebenso das geeignete Maß. Die Zeilenanzahl des Codes ist vermutlich kein guter Indikator für die passende Größe eines Microservices.
Microservices stehen nicht am äußersten Ende des Spektrums: Der Begriff „Nanoservice“ bezeichnet gelegentlich noch kleinere Einheiten. Auch „Functions as a Service“ (FaaS) gehen noch einen Schritt weiter, bringen jedoch zusätzliche Implikationen mit sich.
Größere Einheiten werden teils einfach als „Services“ bezeichnet; andere sprechen von „Macroservices“, wenn sie bewusst größere Dienste gestalten. Der Monolith hingegen – ein großes Softwaresystem, gebaut und betrieben als eine einzige Einheit – ist oft der Ursprung, von dem Organisationen zu Microservices aufbrechen.
Eine Microservices-Architektur impliziert immer ein verteiltes System, bei dem die einzelnen Dienste über das Netzwerk kommunizieren – sei es durch direkte Aufrufe, Abonnieren von HTTP-Feeds oder über Messaging-Dienste wie Apache Kafka, RabbitMQ oder AWS SNS/SQS.
Hauptvorteil von Microservices
Der wichtigste Grund für Microservices ist der Faktor Mensch. Zusammenarbeit mehrerer Teams an einem Monolithen bringt erhebliche organisatorische Hürden mit sich.
Mit Microservices erhalten Teams mehr Freiheit bezüglich ihrer Technologiestacks. Sie müssen sich lediglich auf öffentliche APIs verständigen. Refactorings und Updates von Abhängigkeiten betreffen dann nur das eigene Team. Der wahrscheinlich überzeugendste Punkt: Microservices erlauben es Teams unabhängig voneinander und in hoher Frequenz zu deployen. Richtig umgesetzt, beschleunigen Microservices die Lieferung neuer Funktionen und verkürzen die „Time to Market“.
Hauptnachteil von Microservices
Bis hierher klingt es verlockend – doch nun folgt die Kehrseite: Microservices verlagern die Komplexität ins Netzwerk. Eine robuste Microservices-Architektur zu errichten, ist keineswegs einfach und verlangt meiner Ansicht nach ein höheres Kompetenzniveau der Entwickler als ein Monolith.
Um einen Einstieg zu finden, sei empfohlen, sich mit den „Fallacies of Distributed Computing“ vertraut zu machen. Hierzu zählen:
- Das Netzwerk ist ausfallsicher.
- Die Latenzzeit ist gleich null.
- Der Datendurchsatz ist unbegrenzt.
- Das Netzwerk ist sicher.
- Die Netzwerktopologie wird sich nicht ändern.
- Es gibt immer nur einen Netzwerkadministrator.
- Die Kosten des Datentransports können mit null angesetzt werden.
- Das Netzwerk ist homogen.
Alle diese Annahmen sind falsch und die sich daraus ergebenden Konsequenzen müssen in einer Microservice-Architektur Berücksichtigung finden. Werner Vogels sprach es trefflich aus: „Everything fails, all the time.“
Jeder Microservice braucht seinen eigenen Deployment-Prozess. Die Abhängigkeiten müssen pro Service gepflegt werden. Eine stabile Plattform zum Hosten der Dienste wird zwingend notwendig – und fähige Fachkräfte ebenso. Die eigenständige Verwaltung eines Kubernetes-Clusters stellt selbst für erfahrene Teams eine anspruchsvolle Herausforderung dar, die oft unterschätzt wird.
Hinzu kommen API-Design, Resilienz-Muster, höhere Kosten, verringerte Performance (insbesondere durch Serialisierung/Deserialisierung) und eine deutlich gestiegene topologische Komplexität.
Auch die Freiheit der Technologiewahl will bedacht sein. Teams sollen möglichst autonom sein, aber wenn ein Team sich für eine exotische Sprache entscheidet, kann es schwer werden, das Team mit internen Ressourcen aufzustocken oder fähige Kräfte auf dem Arbeitsmarkt zu finden. Auch nimmt man sich zu einem gewissen Grad die Möglichkeit, von den Erfahrungen anderer Teams im Unternehmen zu lernen.
Ratschläge
Microservices sind keine Technologie, die man einfach einmal ausprobiert. Ihre Einführung ist eine schwer reversible Entscheidung. Fehlentscheidungen können nach Jahren gewaltige Kosten und Risiken nach sich ziehen und die Organisation gefährden.
Architektur wird oft als „jene Dinge, die schwer zu ändern sind“ beschrieben – Microservices gehören genau dazu: Die Entscheidung für Microservices betrifft nicht nur die Softwarearchitektur, sondern formt die gesamte Organisation – in Struktur, Kommunikation und Verantwortung.
Wer den Entschluss fasst, Microservices einzuführen, sollte eine sorgfältige Aufteilung der Dienste sowie eine klare Definition der Verantwortlichkeiten vornehmen. Die zugrunde liegende Architektur sollte hinreichend flexibel gestaltet sein, um sich an veränderliche Anforderungen und Marktbedingungen anpassen zu können. Hilfreich kann hierbei der Ansatz des Domain-Driven Design sein – weniger im Quelltext, sondern vielmehr auf der Ebene der Bounded Contexts. Als ergänzende, kollaborative Modellierungstechniken bieten sich EventStorming und Domain Storytelling an.
Ist ein solcher Wandel bereits im Gange, so darf die Resilienz niemals vernachlässigt werden. Konzepte wie Circuit Breaker sollten zum Grundverständnis gehören. Eine starre Trennung zwischen Entwicklung und Betrieb erweist sich in Microservices-Architekturen oftmals als hinderlich. Empfehlenswert ist daher eine DevOps-Kultur, in der Fehler offen thematisiert und als Lernquellen genutzt werden.
Vorsorge für Disaster Recovery sowie die Durchführung von Post-Mortems sind essenziell. Auch das Studium öffentlich zugänglicher Zwischenfallberichte anderer Organisationen kann wertvolle Erkenntnisse liefern.
Conways Gesetz verdient besondere Beachtung: Die Kommunikationsstrukturen innerhalb der Teams prägen maßgeblich die Systemarchitektur. Hinsichtlich technischer Aspekte wie Zustandslosigkeit und separater Builds lohnt sich eine Auseinandersetzung mit dem Twelve-Factor-App-Modell. Auch wenn es nicht unumstritten ist, bietet es einen guten Einstiegspunkt.
Fazit
Microservices sind zweifellos ein mächtiges Mittel, um komplexe Systeme flexibler, skalierbarer und teamübergreifend besser wartbar zu gestalten. Doch die Einführung einer solchen Architektur ist kein leichtfertiger Schritt. Sie verlagert viele Probleme, die zuvor intern gelöst wurden, in den Bereich verteilter Systeme und verlangt nach neuen Fähigkeiten und Denkweisen.
Dieser Artikel hat aufgezeigt, welche architektonischen und organisatorischen Überlegungen notwendig sind, um Microservices erfolgreich einzusetzen. Von der sorgfältigen Aufteilung der Dienste über den Aufbau von Resilienz und DevOps-Kultur bis hin zum Umgang mit den unvermeidbaren Herausforderungen der verteilten Kommunikation – all dies erfordert mehr als bloße Best Practices: Es verlangt Verständnis, Erfahrung und stetiges Lernen. Die wahre Stärke einer Microservices-Architektur zeigt sich nicht allein in der initialen Einführung, sondern in der fortlaufenden Fähigkeit, sie zu hinterfragen, zu pflegen und weiterzuentwickeln.
Wer sich dieser Reise mit offenen Augen stellt und bereit ist, die versteckten Kosten und Risiken bewusst abzuwägen, kann Microservices zu einem mächtigen Werkzeug im eigenen Unternehmen formen.
Fallacies of Distributed Computing Explained (Whitepaper) EC2/RDS Disruption Summary (2011)