Vom Monolithen zum Microservice
Einführung
Microservices sind in aller Munde, das Thema hat Hochkonjunktur. Überall kann man lesen, wie man Microservices Architekturen aufbauen kann und welche Tools dafür notwendig sind. Wer heute ein neues Projekt als Monolith designt gilt als old-school. Das ist zwar ein grober Fehler, mit einen Monolithen zu starten ist in vielen Fällen die besere Alternative, das ist aber nicht unser Thema heute. Ich möchte heute auf ein Thema eingehen, das uns vermutlich die nächsten Jahre beschäftigen wird. Wie können wir eine existierende, Monolithische Anwendung in eine Microservices Architektur überführen?
In diesem Artikel werde ich auf einige Strategien und Muster eingehen, die wir in vergangenen Projekten angewendet haben, um monolithische Applikationen in eine Microservices Architektur zu überführen. Ich werde explizit weder auf die Definition von Microservices eingehen noch bestimmte Tools erwähnen, das kann man woanders in ausreichender Tiefe und Breite lesen.
Ansatzpunkte
Bei allen Fällen die ich erlebt habe, stellte sich erst einmal die Frage, wo man ansetzen soll. Wie kann man sich der Thematik annähern? Betrachten wir zuerst die möglichen Ausgangslagen. Der gemeinsame Nenner ist meistens, dass es eine monolithische Anwendung gibt, mit der es Probleme gibt. Hier findet sich meistens schon der erste Hinweis darauf, ob eine Überführung in eine Microservice Architektur überhaupt Sinn macht. Schauen wir uns diese Gründe an:
- Die Applikation ist schlecht oder gar nicht mehr wartbar
- Die Applikation lässt sich nicht in akzeptabler Zeit bzw. automatisiert deployen
- Das Deployment der Applikation ist immer mit Downtime verbunden
- Fehler in bestimmten Teilen der Applikation führen zu einem Totalausfall der Anwendung
- Die Applikation skaliert schlecht oder gar nicht
- Die Applikation lässt sich nicht mit vertretbarem Aufwand erweitern
- Teile der Applikation lassen sich nicht ohne extrem negativen Auswirkungen auf das Gesamtsystem austauschen
Können mehrere dieser Gründe herangezogen werden, so ist es zumindest empfehlenswert, weiter zu untersuchen, ob eine Microservices Architektur besser geeignet wäre.
Erste Annäherungsversuche
UI Trennung
Ein erster Ansatzpunkt kann sein, zu untersuchen ob die UI - sofern die Applikation überhaupt eine hat - vom Rest getrennt werden kann. Je nach Art der Applikation kann die Präsentationsschicht recht umfangreich sein. Umso mehr lohnt es sich, diese zu extrahieren. Allerdings muss hier evtl. ein Zwischenschritt eingeführt werden. Ist die Präsentationsschicht zu komplex, ist es ratsam, diese erst als einen zweiten Monolithen zu extrahieren und zwischen dem Frontend-Monolithen und dem Backend-Monolithen eine Schnittstelle einzuziehen. Erst im nächsten Schritt kann dann damit begonnen werden, diese millerweile kleineren Monolithen in Services aufzulösen.
Monolithen Modularisieren (Orthogonale Transformation)
Viele monolithische Anwendungen sind logisch nach einem Schichtenmodell segmentiert. Stark vereinfacht sind diese Segmente von unten nach oben: Persistenzschicht, Domänenschicht, Anwendungsschicht und Präsentationsschicht. Grafisch dargestellt kann diese Architektur als übereinander gestapelte Rechtecke dargestellt werden. Bei komplexen Anwendungen kann es sinnvoll sein, die Architektur des Monolithen erst einmal orthogonal zu transformieren, indem man innerhalb des Monolithen modularisiert. Die Darstellung der resultierenden Architektur besteht dann aus nebeneinander stehenden Boxen. Ein solcher Monolith lässt sich einfacher in eine Microservices Architektur übertragen.
Cross Cutting Concerns
Ein weiterer, vorbereitender Punkt kann sein, die sog. Cross Cutting Concerns zu extrahieren. Kandidaten hierfür können, je nach Art der Anwendung, sein: Logging, Encryption, Authentication, Messaging, usw. Diese Themen sind oft technisch gut kapselbar, so dass sich hieraus einfacher Services extrahieren lassen, die dann über eine definierte Schnittstelle angebunden werden können.
Produkte extrahieren
Während sich die o.g. cross cutting concerns eher auf einer technischen Ebene bewegen, haben komplexe Anwendungen auch eine ganze Reihe an fachlichen Komponenten. Viele dieser Komponenten sind fertige Lösungen, die irgendwann in den Monolithen, mal mehr mal weniger gut gekapselt, integriert worden sind. Diese sind ebenfalls Kandidaten für eine einfache Extraktion zu einem Service. Beispiele hierfür sind: Workflow Engines, Search Engines, Affiliate Marketing, Recommendation Engines, CMS, usw.
Zweite Iteration, eine Ebene tiefer
Im vorherigen Abschnitt habe ich die "Low Hanging Fruits" der Microservices Extraktion aufgeführt. Nun bleibt der harte Kern des alten Monolithen übrig. Hier kann man nicht nach Schema F vorgehen, da die Herangehensweise zu stark von der vorliegenden Software abhängt. Trotzdem haben wir Muster identifiziert, die sich in den letzten Projekten wiederholt haben. Diese bespreche ich im folgenden Abschnitt.
Asynchrone Verarbeitung
Oben hatte ich bereits aufgeführt, dass z.B. Messaging ausgegliedert werden kann. Nun bietet es sich an, sich die Komponenten im Monolithen anzuschauen, die asynchron, evtl. über Messaging, kommunizieren. Da hier erfahrungsgemäß die Kopplung geringer ist, bieten sich solche Komponenten an.
Datenhaltungsparadigmen
In vielen Anwendungen sieht man eine polyglotte Datenhaltung. D.h. es werden unterschiedliche Datenhaltungen für unterschiedliche fachliche oder technische Anforderungen verwendet. Ich empfehle diese Datenhaltungen sowie die Komponenten, die diese verwenden, zu untersuchen. Oft können diese Kandidaten für eine Extraktion sein.
Threads
Threads sind in manchen Fällen ebenfalls lohnenswerte Einstiegspunkte. In vielen Anwendungen werden Threads verwendet, um sehr spezifische Aufgaben auszuführen. Da ein Thread von Natur aus eine lose Kopplung und eine hohe Kohärenz zum Gesamtsystem haben sollte, bietet es sich an, diese auf ihre Extraktionsfähigkeit zu untersuchen.
Algorithmen
Algorithmen bestehen oft aus vielen Klassen oder Modulen, die nur zur Erfüllung der Aufgabe des Algorithmus da sind. Diese sind ebenfalls Kandidaten, um extrahiert zu werden, da hier auch eine lose Kopplung mit einer hohen Kohärenz gegeben ist.
Zusammenfassung und Ausblick
Die o.g. Ansätze sind aus unseren Erfahrungen in Projekten verschiedener Größe entstanden. Wir gehen fest davon aus, dass dieses Thema in den kommenden Jahren immer wieder auftauchen wird. Wir freuen uns auf den regen Austausch mit Kunden, Partnern und der Community, um Ideen und Erfahrungen auszutauschen.