Risiko Microservices? Vor- und Nachteile einer verteilten Architektur
Microservices sind die perfekte Lösung für gewisse Probleme. Doch unpassend eingesetzt, können sie das ganze Projekt ruinieren. Worauf gilt es zu achten?
![Lupe, unter der sich ein Warndreieck befindet.](https://heise.cloudimg.io/width/610/q85.png-lossy-85.webp-lossy-85.foil1/_www-heise-de_/imgs/18/4/6/3/3/2/1/9/shutterstock_2200566215-c0996bdc49784548.jpeg)
(Bild: Dilok Klaisataporn/Shutterstock.com)
- Golo Roden
Vor ungefähr einer Woche habe ich einen Blogpost geschrieben, zu dem ich viel Feedback erhalten habe: "12 Regeln für die perfekte (Micro-)Service-Architektur". Darin habe ich zwölf Regeln vorgestellt, die sich für uns bei der the native web GmbH in den vergangenen Jahren für die Konzeption, den Entwurf und die Entwicklung von Microservices bewährt haben. Sehr deutlich habe ich außerdem gesagt: "Your mileage may vary", also auf gut Deutsch: Die Tatsache, dass sich diese Regeln für uns bewährt haben, bedeutet noch lange nicht, dass sie auf Sie, Ihr Team und Ihre Anforderungen 1:1 übertragbar seien.
Des Weiteren habe ich auch nicht behauptet, dass Microservices der einzig wahre Architekturansatz seien. Aber ich gehe in einem Blogpost über die Architektur von Microservices natürlich davon aus, dass der Text primär von Menschen gelesen wird, die mit der Konzeption, dem Entwurf und der Entwicklung von Microservices zu tun haben – oder die sich zumindest zukünftig dafür interessieren werden.
Achtung, Achtung! Bitte halten Sie sich von Microservices fern!
Daher war ich überrascht, dass rund die Hälfte der Kommentare – sei es hier auf heise Developer, auf YouTube, per E-Mail oder im persönlichen Gespräch – den Einsatz von Microservices an sich infrage gestellt hat, sinngemäß: Ja, das könne man schon alles so machen, aber als Allererstes solle man doch gründlich hinterfragen, ob Microservices an sich eine gute Idee seien oder nicht. Überrascht war ich deshalb, weil ich es zum einen für selbstverständlich halte, dass man ein Architekturprinzip im Vorfeld auf Eignung prüft, und ebendiese Frage zum anderen gar nicht das Thema des Blogposts war.
Empfohlener redaktioneller Inhalt
Mit Ihrer Zustimmmung wird hier ein externes YouTube-Video (Google Ireland Limited) geladen.
Ich bin damit einverstanden, dass mir externe Inhalte angezeigt werden. Damit können personenbezogene Daten an Drittplattformen (Google Ireland Limited) übermittelt werden. Mehr dazu in unserer Datenschutzerklärung.
Anscheinend besteht eine Notwendigkeit, vor dem Einsatz von Microservices zu warnen, denn damit habe man "schon schlechte Erfahrungen gemacht". Dass das gleiche auch für andere Architekturansätze wie Monolithen, Client-Server oder Peer-to-Peer gilt, fällt dabei gerne unter den Tisch. Interessant finde ich, dass ich diese Reaktion sehr häufig auf die Erwähnung von Microservices erlebe. Ich mag auch gar nicht abstreiten, dass nicht die eine oder der andere tatsächlich schon schlechte Erfahrungen mit Microservices gemacht hat – mich wundert nur, dass stets nur bei Microservices so vehement darauf hingewiesen wird.
Deshalb habe ich mir überlegt, dass es vielleicht sinnvoll sein könnte, einmal die Frage zu stellen, wann Microservices eine gute und wann sie eine schlechte Idee sind. Mit anderen Worten: Über welche Aspekte lohnt es sich nachzudenken, bevor man auf Microservices setzt, damit ein Projekt nachher nicht tatsächlich in einem Fiasko endet?
Und übrigens, bevor nun jemand argumentiert, dass selbst Amazon inzwischen auf Microservices verzichten würde: Zu diesem Gerücht habe ich mich vor geraumer Zeit bereits geäußert. Also falls Sie dieses Argument hätten anbringen wollen, dann schauen Sie sich bitte vorab das Video "Microservices sind doof – sagt Amazon?!" an.
Argument #1: Komplexität der Architektur
Kommen wir nun zum ersten häufig genannten Argument gegen Microservices, nämlich der deutlich höheren Komplexität der Architektur. Per Definition sind Microservices eine verteilte Architektur, es handelt sich also bei einer Service-basierten Anwendung um ein verteiltes System. Der US-amerikanische Informatiker Andrew S. Tanenbaum hat ein solches System wie folgt definiert:
"Ein verteiltes System ist ein Zusammenschluss unabhängiger Computer, die sich für den Benutzer als ein einziges System präsentieren."
Tatsächlich gibt es von dieser Definition auch noch eine humoristische Abwandlung, und zwar:
"Ein verteiltes System ist ein System, das nicht das macht, was es soll, weil ein Computer ausgefallen ist, von dem Sie weder wussten, dass er existiert noch, dass er für irgendetwas wichtig ist."
Doch Spaß beiseite: Es liegt auf der Hand, dass verteilte Systeme in technischer Hinsicht komplexer sind als nicht-verteilte Systeme. Das hängt vor allem mit Problemen rund um die Kommunikation zwischen den einzelnen beteiligten Parteien zusammen, also mit Themen wie Konsistenz, Synchronisation, Verfügbarkeit und so weiter.
In diesen Zusammenhang fällt dann auch das sogenannte CAP-Theorem, das (vereinfacht ausgedrückt) besagt: Wenn in einem verteilten System ein Netzwerkausfall stattfindet und dadurch eine Partitionierung entsteht (das entspricht dem "P"), dann kann man sich aussuchen, ob man entweder die Konsistenz (also das "C") oder die Verfügbarkeit (also das "A", das hier für "Availability" steht) bewahren möchte. Beides zusammen ist nicht möglich.
Das bedeutet, dass man sich bei verteilten Systemen deutlich mehr Gedanken machen muss, wie man mit Konsistenz und Verfügbarkeit umgeht, was wiederum einiges an Wissen und Erfahrung erfordert. Vor allem benötigt man für ein verteiltes System jedoch eines, nämlich einen guten Grund, warum man ein System überhaupt als verteiltes System entwerfen möchte. Man sollte es nicht deshalb machen, weil es "interessant wirkt" oder "cool klingt".
Der vermutlich primäre Grund, ein System als verteiltes System gestalten zu wollen, ist (und das steckt sogar schon in der Definition von Andrew S. Tanenbaum), dass man eine hohe Unabhängigkeit zwischen den einzelnen Teilen anstrebt, und zwar in technischer, organisatorischer und vor allem auch in fachlicher Hinsicht. Darüber hinaus wird gerne noch genannt, dass man eine Technologie nicht systemrelevant werden lassen möchte, dass man mit Microservices eine höhere Flexibilität und eine bessere Anpassbarkeit bekäme, dass man ein verteiltes System gezielter skalieren könne und so weiter – aber die Unabhängigkeit, ist die eigentlich treibende Kraft hinter verteilten Systemen. Und wenn der Bedarf daran nicht gegeben ist, dann eignet sich ein stärker zentralisierter Ansatz höchstwahrscheinlich deutlich mehr.
Daher muss man sich die Frage stellen: Benötigt man technische, organisatorische und vor allem fachliche Unabhängigkeit?
Argument #2: Deployment und Infrastruktur
Kommen wir zum zweiten häufig genannten Argument gegen Microservices, nämlich dem Deployment und der Infrastruktur. Klar ist, dass Microservices komplexere Deployments nach sich ziehen, und zwar nicht zuletzt deshalb, weil schlichtweg mehr zu deployen ist. Natürlich ist das XCOPY-Deployment eines einfachen Monolithen, der auf einem einzigen Server mit einer einzigen Instanz läuft, bedeutend einfacher.
Allerdings funktioniert das Deployment von Microservices eigentlich immer sehr ähnlich, und zwar vollkommen unabhängig davon, um welche Anwendung es sich dabei handelt. Das bedeutet, dass man das Know-how dafür problemlos "fertig von der Stange" einkaufen kann. Weder muss man hierbei viel experimentieren noch muss man viel herausfinden – es braucht lediglich jemanden, die oder der das schon einmal gemacht hat und die oder der sich mit den entsprechenden Technologien auskennt. Also, allen voran: Container, Docker und Kubernetes.
Mich persönlich überzeugt dieses Argument nicht so richtig, denn ja, die Komplexität ist zwar höher, aber nicht nennenswert höher – und dafür bekomme ich im Umkehrschluss eine viel niedrigere Komplexität in der Fachlichkeit der einzelnen Services. Das heißt, jeder einzelne Service wird einfacher zu entwickeln, weil er deutlich kleiner und überschaubarer ist. Und da gerade das der Punkt ist, den ich nicht von der Stange kaufen kann, ist die Ersparnis hier viel mehr wert als das, was ich beim Deployment potenziell an zusätzlichen Kosten habe. Denn ja, einerseits wird eine einfache, standardisierte und immer gleiche Aufgabe etwas komplexer, doch dafür erhält man eine viel niedrigere Komplexität bei den Dingen, die ohnehin schwierig, anspruchsvoll, zeitaufwendig und individuell sind. Und das klingt für mich persönlich eigentlich nach einem ziemlich guten Handel.
Diese Gegen-Argumentation basiert natürlich auf der Annahme, dass man mit Containerisierung, Docker, Kubernetes & Co. halbwegs vertraut ist. Wer heute immer noch von Hand mit Shell-Skripten auf Bare-Metal unterwegs ist, der wird Schwierigkeiten mit dem effizienten Deployment von Microservices haben. Allerdings zeigt die Erfahrung, dass das auch für alle anderen Arten von Deployments gilt. Falls Containerisierung & Co. für Sie und Ihr Team tatsächlich noch Neuland sein sollten, dann ist das etwas, was Sie schleunigst ändern sollten – zumindest, wenn Sie im Bereich Web und Cloud tätig sind. Als Einstieg kann ich Ihnen unseren kostenlosen Docker Deep-Dive empfehlen, zu dem es auch noch einige Fortsetzungen und einen gesonderten Deep-Dive zu Kubernetes gibt.