Microservices und ihre Alternativen
Vorteile von Microservices
Betrachtet man hierbei die gängigen Beschreibungen dessen, was als Microservice wahrgenommen wird, so erklärt sich die Begeisterung noch auf weitere Weisen. Als Microservices werden umgangssprachlich gern kleine Dienste verstanden, die zumindest zur Laufzeit voneinander entkoppelt sind und über ein bestimmtes Kommunikationsmedium miteinander interagieren. Dieses Medium ist meist ein Netzwerk und wird über einen Service Bus oder über entsprechende Endpunkte zum Beispiel mit REST oder RPC umgesetzt. Dies verhindert, dass die Dienste über etwas anderes als ihre öffentlichen Schnittstellen angesprochen werden. Da sie physisch voneinander getrennt sind und in eigenen Prozessen, gegebenenfalls sogar auf völlig unterschiedlicher Hardware laufen, können sie zeitgleich auch leichter skaliert werden.
Durch die Nutzung standardisierter Austauschformate kann darüber hinaus jedes Team seine Dienste technisch so umsetzen, wie es sie selbst umsetzen möchte. Dadurch können sich die Entwickler auf die Technologien konzentrieren, mit denen sie sich auskennen. Sollte ein Dienst ausserdem einmal zu komplex oder zu schlecht wartbar sein, kann er aufgrund seiner geringen Grösse vergleichsweise leicht ausgetauscht werden. Aus den gleichen Gründen sind die Dienste auch automatisch viel leichter verständlich und besser testbar als der Code innerhalb eines gewachsenen Monolithen. Dass sie aufgrund ihrer Natur auch ausfallsicherer sind, ist selbstverständlich.
Neben der rein technischen Skalierung erlauben Microservices aber auch eine organisatorische Skalierung. Neue Teams können sehr viel schneller produktiv arbeiten, als dies bei einem Monolithen der Fall ist. Diese neuen Teams erstellen eigene Dienste auf der grünen Wiese und müssen sich daher nicht so sehr um das kümmern, was bereits vorhanden ist. Insofern sie die Schnittstellen der anderen Dienste verstehen, können sie diese über Standardvorgehensweisen nutzen und brauchen sich nicht mit dem lästigen Klein-Klein von deren Implementierung herumschlagen. Gerade Firmen wie Uber und Netflix konnten dank dieser Skalierbarkeit eine immense Entwicklungsgeschwindigkeit erreichen und binnen kurzer Zeit auf Marktveränderungen reagieren.
Was sind Microservices wirklich?
Das klingt fast zu gut, um wahr zu sein, und tatsächlich ist es das auch. Denn die zuvor genannte landläufige Beschreibung spart sehr viele der eigentlichen Kernkonzepte von Microservices aus und verschweigt die wichtigsten Problemfelder. Der Hauptfehler, der hierbei gern gemacht wird, ist, dass die Argumentation sehr stark von der technischen Seite getrieben wird. Das Kernkonzept von Microservices ist aber, dass sie gerade eben nicht technisch getrieben sein sollten, sondern fachlich.
Laut dem Autor Sam Newman sind Microservices Dienste, die unabhängig voneinander deployt werden können, um eine bestimmte Business-Domäne modelliert werden und über Netzwerke miteinander kommunizieren. Sie sind somit eine besondere Form der serviceorientierten Architektur, bei der speziell Rücksicht darauf genommen wird, wie die Grenzen der Dienste geschnitten werden. Genau dieser Schnitt der Dienste ist es indes, der in der Praxis zu einigen Schwierigkeiten führt.
Deployment Unit versus Bounded Context
Microservices und Domain Driven Design (DDD) teilen sich viele gemeinsame Überzeugungen, wodurch einige Begriffe des einen gelegentlich im Kontext des anderen verwendet werden. Trotzdem sind sie nicht das Gleiche. DDD ist eine Methodik samt diverser Werkzeuge, die sich damit beschäftigt, Software auf Basis der tatsächlichen Bedarfe aus den Fachbereichen beziehungsweise Fachdomänen zu gestalten. Microservices als Architekturmuster können hierbei eine Möglichkeit sein, wie die Ziele erreicht werden, die durch DDD herausgearbeitet wurden.
Ein Begriff, der in diesem Zusammenhang oft falsch verstanden wird, ist der Bounded Context. Er beschreibt einen fachlichen Zusammenhang, der in sich geschlossen ist und gegen andere fachliche Bereiche abgegrenzt werden kann. In der Umsetzung bedeutet dies meist, dass Bezeichnungen innerhalb des einen Kontexts ganz andere Bedeutungen haben als in einem anderen. So kann etwa eine Rechnung, die beim Einkauf eingeht, ganz andere Eigenschaften und Bedeutungen haben als eine Rechnung, die vom Verkauf ausgestellt wird.
Die Theorien hinter Bounded Contexts sprengen den Rahmen dieser Erklärung und sollen daher hier nicht weiter betrachtet werden. Es ist jedoch wichtig zu wissen, dass sie vor allem ein Mittel sind, um Software strategisch zu planen.
Bei der Umsetzung dieser Strategien kann dann auf Services oder Module zurückgegriffen werden. So können mehrere Microservices einen Bounded Context abbilden, damit den gleichen fachlichen Zielen dienen und das gleiche Daten-Model nutzen.
Es ist deshalb eine falsche Annahme, dass jeder Microservice selbst auch ein Bounded Context sei. Vielmehr wird die Bezeichnung einer Deployment-Einheit beziehungsweise einer Deployment Unit dem gerechter, was Microservices eigentlich sein sollen. Damit wird all das bezeichnet, was als Einheit gemeinsam veröffentlicht wird und alleinstehend veröffentlicht werden kann. Hierzu gehören beispielsweise ein Installer, Datenbankskripte und natürlich der kompilierte Quellcode. Ein Monolith ist aufgrund seiner Natur schon eine sehr grosse Deployment Unit. Microservices hingegen sind vergleichsweise kleine Units, die voneinander unabhängig deployt werden können. Sollten die Dienste nicht unabhängig deployt werden, sind es laut Definition keine Microservices mehr, und die Unit ist entsprechend grösser zu betrachten, da sie mehrere Dienste umfasst.
Bild 1 zeigt beispielsweise eine Aufteilung rein auf Basis der technischen Schichten. Eine fachliche Trennung ist daher in Bild 1 nicht zu erkennen. Bild 2 wiederum nimmt eine Auftrennung mit dem Ziel einer Skalierung vor. Wobei Auftrennung hier nicht das richtige Wort ist: Tatsächlich werden nur mehrere Instanzen der gleichen Software bereitgestellt. Das gleiche Vorgehen wurde eigentlich auch bei Bild 3 verfolgt. Hier gibt es keine Unterscheidung, warum die Logik und die Datenhaltung konkret in eigenen Diensten vorliegen. Vielmehr wird alles in einem grossen Frontend-Monolithen wieder zusammengeführt.
Ein solcher Fall liegt beispielsweise vor, wenn man einen typischen Desktop-Client betrachtet, der verschiedene Backend-Services anspricht, wie es bei einer serviceorientierten Architektur der Fall ist. Bild 3 zeigt demnach keine Microservice-Architektur, sondern eine serviceorientierte Architektur. Microservices werden die Dienste erst durch ihre fachliche Auftrennung und Entkopplung voneinander, wie sie beispielsweise in Bild 4 zu sehen ist. Hier wurde absichtlich auf die Darstellung der Präsentationsschicht verzichtet, um die Komplexität der Abbildung zu verringern.
Die Auftrennung der Dienste erfolgte im Beispiel anhand der Fachabteilungen, für die sie entwickelt wurden, das heisst die Verkaufsabteilung, die Personalabteilung und die Einkaufsabteilung. Je nachdem, wie umfangreich die abzubildenden Prozesse sind, könnten solche Dienste aber noch weiter zerlegt werden. So wäre beispielsweise ein Dienst für die Rechnungslegung vorstellbar, oder ein Dienst für das Beantragen von Urlaub.
Autor(in)
Hendrik
Lösch