In dieser Artikelserie wollen wir einmal beleuchten, wie ein Entscheidungsweg und eine Transformation zu einer Architekturumstellung auf Microservices aussehen könnte.
Bei den Musketieren heißt es: “Einer für alle, alle für einen”. So schön das klingt gilt es für unseren Artikel nicht. Ganz im Gegenteil beleuchten wir ein Entweder-oder. Die Entscheidung zwischen alle für einen, ein Microservice-Architekturansatz oder einer für alle, ein monolithischer Ansatz.
Als ersten Schritt in der Entscheidungsfindung betrachten wir das Projektumfeld. Bei einem Legacy Projekt stellt sich immer die Frage nach der Komplexität und der Anzahl an technischen Schulden, die sich im Laufe der Zeit angesammelt haben. Gibt es keine Probleme wie zum Beispiel steigenden Aufwand der Entwicklung oder sehr hohen Onboarding Aufwand, dann besteht auch kein Druck, die aktuelle Lösung zu hinterfragen. Die Erfahrung zeigt jedoch, dass langlaufende monolithische Projekte eher zu sehr hoher Komplexität und sinkender Developer Performance führen.
Bei einem Greenfield Projekt hat man grundsätzlich immer die Flexibilität, sich sowohl für den einen als auch für den anderen Architekturansatz zu entscheiden. Oft ist es empfehlenswert sich die langfristige Entwicklung vor Augen zu führen, um eine Entscheidung für die Architektur treffen zu können. Hier gilt es zu bewerten, wie sich ein Projekt entwickeln wird: Wie groß sind die Entwickler Teams? Welche Features und weiteren Entwicklungen werden in den kommenden Jahren erwartet? Diese Punkte können Einfluss auf die Entscheidung der Architektur haben. Ohne auf Details einzugehen, bleibt uns an dieser Stelle nur die beliebte IT Antwort: “Es kommt darauf an."
Folgenden Faktoren können bei einer Entscheidung der Architektur helfen.
Bei einem kleinem Projektumfang ist meist die Monolith Architektur zu favorisieren, da ein Teil oder eventuell sogar alle benötigten Features vom Monolithen abgedeckt werden können und meist keine größeren Abstimmungen notwendig sind. Ab einer gewissen Größe des Umfangs kann eine Microservice Architektur jedoch mehrere Vorteile bieten. Jedes Team hat einen klaren Scope und die Schnittstellen untereinander sind klar definiert. Es gibt eine gewisse Flexibilität, so dass zum Beispiel eine Implementierung problemlos komplett ausgetauscht werden kann, sofern die Schnittstelle und definierte Parameter eingehalten werden. Letzten Endes hängt auch viel an den Fähigkeiten der Projektmitarbeiter.
Die Messbarkeit verschiedener Faktoren wie des Fortschrittes und der Kosten sowie die Abschätzung der Risiken sind wichtige Entscheidungsfaktoren, da diese den Projektablauf besser planen lassen. Nach dem initialen Aufsetzen eines Monolithen ist bereits ein funktionsfähiges System vorhanden und die Fortschritte sind daher klar erkennbar. Neue Features können direkt im Anschluss entwickelt, getestet und in Betrieb genommen werden.
Bei Microservices sind erste Ergebnisse oft erst nach einem fortgeschrittenen Entwicklungsstand durch das Zusammenspiel mehrerer Microservices erkennbar. Auch Kosten können schwerer zu erfassen sein. Zum Beispiel können die Betriebskosten bei Cloudlösungen je nach Nutzung stark schwanken und auch ein Gesamtüberblick über den Projektfortschritt mag schwieriger zu erfassen sein.
Bei einem Monolithen fällt die Kostenschätzung leichter. Der Projektfortschritt bleibt sehr einfach transparent. Die Betriebskosten sind klar kalkulierbar.
Ein weiteres Thema ist es, die Risiken der jeweiligen Architektur abzuschätzen. Monolithen neigen zu wachsender Komplexität und damit sinkender Performance der Entwicklungsteams und damit zu steigendem Wartungsaufwand. Microservices bringen hoch komplexe Anforderungen an den Betrieb mit sich, wie zum Beispiel den Schutz der komplexen Systeme nach außen. Wie geht man mit Ausfällen einzelner Services um? Für alle Fragen gibt es bereits Antworten, aber natürlich kommt nichts umsonst.
Eine grobe Vorstellung eines langfristige Projektziels hat auch Einfluss auf unsere Entscheidung. Ohne auf Details eingehen zu wollen, ist zumindest die Frage wichtig, wie flexibel meine Lösung sein soll. In einer Microservice Architektur wird es einfacher sein, einzelne Services, Anbieter oder Produkte auszutauschen. In einem Monolithen kann das schwieriger werden. Oft bleibt die Produktwahl des Monolithen selbst auf lange Zeit ein limitierender Faktor der nicht ohne großen Aufwand ersetzt werden kann.
In den letzten Jahren zeigt sich auch, dass allein das Staffing eines Projektes Schwierigkeiten mit sich bringt: Finde ich überhaupt genügend Entwickler, die meinen Monolithen weiter entwickeln können?
Hier ist eine moderne Architektur, am besten gepaart mit neuen Technologien, eher reizvoller für Entwickler.
Nicht nur das Staffing selbst, sondern auch die Einarbeitung ist ein wichtiger Punkt. Anforderungen an einzelne Projektmitglieder schwanken sehr stark von Projekt zu Projekt und auch zwischen den beiden Architekturen, die wir betrachten. Beim Thema Entwickler bleibend, stellen Monolithen häufig mehr Anforderungen an Einzelne als Microservices. Warum ist das so? Die meisten Monolithen sind eine Sammlung verschiedener Frameworks, um die Anforderungen zu erfüllen. Diese müssen alle beherrscht werden und meist muss mehr als eine Domäne innerhalb des Monolithen bedient werden. Bei Microservices bleibt der Scope des einzelnen Services klar definiert und auch reduziert (im Vergleich). Auch werden die eingesetzten Frameworks sehr wahrscheinlich nicht in einer gleich großen Zahl auftreten. Das vereinfacht den Einstieg neuer Entwickler im Vergleich zum Monolithen.
Auf der anderen Seite wird von Entwicklern im Microservice Umfeld zumindest ein grundlegendes Verständnis des Betriebs verlangt. Das wird beim Monolithen nicht in der gleichen Tiefe notwendig sein. Die Komplexität der Infrastruktur kann daher auch schwerer verständlich sein.
Davon abgesehen steigen die Anforderungen an Testing, Error Tracing und Monitoring enorm mit Microservices.
Betrachtet man das schon mehrfach angesprochene Thema Betrieb, gibt es hier einen sehr großen Unterschied. Im Microservice Umfeld ist es deutlich komplexer. Wenn man nur Probleme bedenkt, die bei einer Kommunikation von Webserver, Application Server und der Datenbank auftreten können, kann man sich auch vorstellen, was dies für dutzende Microservices, die miteinander kommunizieren, bedeutet. Nur ein paar Stichpunkte: Ausfallsicherheit, Security, Netzwerkkommunikation, Monitoring, Error Tracing...
Aber nicht nur Error
Tracing oder Monitoring sind Schwierigkeiten eines großen Projektes.
Sie sind nur ein Teil der Problematik der Wartung der Software, bzw. des
gesamten Systems.
Wie schon erwähnt neigen Projekte zu "historischen
Strukturen", die dann schwer verständlich und langfristig auch fragwürdig
sein können. Da man in Monolithen eine höhere Kopplung hat, wird ein
Refactoring schwerer als in einer Microservice Architektur, bei der man
außer den Schnittstellen erst einmal nahezu völlig unabhängig unter den
Diensten ist.
So können sich die Entwickler auf die einzelnen
Anforderungen des Microservices konzentrieren, ohne zu viele Seiteneffekte
befürchten zu müssen.
Wirft man nun einen Blick auf die Time-to-Market, so hat die
Standardsoftware in Form eines Monolithen klar die Nase vorn. Eine
Plattform wie SAP Commerce bietet für einen gewissen Anwendungsbereich
bereits eine bestehende Plattform mit einer Menge an Features. Somit ist
der initiale Entwicklungsaufwand, bis man ein grundsätzlich marktreifes
Produkt vorweisen kann, relativ gering.
Setzt man auf eine
Microservice-Architektur, ist es natürlich dennoch möglich, verschiedene
bestehende Produkte zu kombinieren. Zu einer solchen
Entscheidungsfindung gehört jedoch eine Menge architekturales Know-How,
um die bestmöglichen Frameworks und Produkte für die jeweiligen
Anwendungsfälle zu ermitteln. Hierbei ist der Entwicklungsaufwand - in
vielen Fällen auch lediglich Konfiguration - am Anfang deutlich höher,
da die Basis für die einzelnen Komponenten auf allgemeineren
Anwendungsfällen basiert. Im weiteren Verlauf geht der
Microservice-Ansatz allerdings in Führung, da einzelne Services sich
schneller und flexibler entwickeln und releasen lassen. Beides mit der
Grundannahme, dass man sich im Laufe eines Projektes mehr und mehr vom
Standardsatz der Features entfernt und mehr individualisierte Lösungen
implementiert.
Ein großer Vorteil, der sich durch Microservices ergibt, ist mit Sicherheit die Skalierbarkeit. Durch die Trennung der Verantwortlichkeiten zwischen den einzelnen Services ist es oft möglich, einen Service relativ problemlos in die Breite zu skalieren. Cloud-Anbieter wie AWS oder Azure und deren Frameworks machen das Setup solcher Architekturen sehr einfach.
Nehmen wir als Beispiel den Import neuer Inhalte in ein Shopsystem. Unabhängig in welcher Art die Daten bereitgestellt werden, muss im reinen Monolithen die Verarbeitung auf der selben Plattform geschehen, die auch eine Menge anderer Shop-relevanter Prozesse abdeckt. Hier kann zwar die Last durch mehr Ressourcen, sprich Server, bezwungen werden, was allerdings schnell kostspielig werden kann. Besonders wenn nur potentielle Peaks zu bedienen sind.
Das gleiche Problem in einer Cloud-Computing-Plattform wie zum Beispiel AWS Lambda, ergibt im Vergleich eine Reihe von Vorteilen. Durch das selbständige Skalieren können die zu importierenden Daten quasi parallel verarbeitet werden. Die Skalierung ist nahezu endlos. Bottlenecks entstehen dann bei der Persistierung, zum Beispiel in einer Datenbank. Auch dies kann die Kosten schnell in die Höhe treiben, allerdings entstehen Kosten auch nur, wenn tatsächlich etwas verarbeitet wird.
Doch was, wenn man mit einem Fehler nicht weiterkommt? Bei einer Standardsoftware hat man hier klassische Mittel zur Verfügung. Die Entwickler Teams können die Software im Normalfall problemlos debuggen. Hat man sich für eine verteilte Architektur entschieden, ist unter Umständen viel mehr Know-How aus verschiedenen Bereichen gefragt. Ein Problem, das nicht klar auf einen Service eingrenzbar ist, kann sehr schwer zu finden sein.
Als nächstes wollen wir uns den Faktor Kommunikations- und Projektstrukturen anschauen. Grundsätzlich ist zu sagen, dass die Strukturen bei der monolithischen Architektur sowohl in der Kommunikation als auch im Projekt enger verwoben und voneinander abhängig sind. Das geht damit einher, dass bei einem Monolithen alle Entwickler auf einem System arbeiten. Mit der Microservice Architektur besteht die Projektstruktur lediglich aus den voneinander abhängigen Services. Bei Entwicklungsteams, die an unterschiedlichen Services arbeiten, die keine Abhängigkeit zueinander haben, besteht daher auch keine Notwendigkeit miteinander zu kommunizieren. Die Kommunikations- und Projektstruktur ist dadurch losgelöst und die Verantwortlichkeit beschränkt sich nur auf die eigenen Microservices. Das kann sowohl als Nachteil als auch als Vorteil gesehen werden.
Wenn man sich für den Wechsel von einem Monolithen zu einer Microservice Architektur entscheidet, benötigt die Firma dafür auch eine gewisse Transformationsbereitschaft. Dieser Wechsel bringt viel Umdenken und viele neue Ansätze mit sich. So ein Prozess kann bei sehr starren Strukturen schnell ins Leere laufen. Eine Transformation sollte von allen Projektteilnehmern getragen und unterstützt werden, damit sie nach Plan von statten gehen kann und nicht unnötig in die Länge gezogen wird. Nur so kann auch die Stärke zu tragen kommen.
Mit einer der wichtigsten Faktoren sind die Kosten für den Betrieb sowie für die Entwicklung.
Für
den Betrieb sind die Kosten bei einer monolithischen Architektur recht
konstant und abhängig von den zu verwendeten Systemen. Die Kosten für
den Betrieb einer Microservice Architektur hingegen skalieren mit dem
Projektumfang und können je nach benötigten Features schnell steigen.
Dies hat auch damit zu tun, dass viele einzelne Services extra bezahlt
werden müssen, geht man von gängigen Plattformen wie AWS oder Azure aus.
Die Kosten für die Entwicklung bei einer monolithischen Architektur
steigen hingegen mit wachsendem Projektumfang und Komplexität, da
beispielsweise die Einarbeitung neuer Entwickler mit einem immer höher
werdendem Zeitaufwand verbunden ist, was der steigenden Komplexität der
Projektstruktur geschuldet ist.
Die Microservice Architektur hat hier
den Vorteil, dass die einzelnen Microservices unabhängig vom
Projektumfang entwickelt werden und die Kosten daher recht konstant
bleiben.
Wesentliche Risiken liegen in der korrekten Unterteilung der Kernfunktionen. Eine zu feingranulare Strukturierung kann dabei Performanceeinbußen mit sich bringen und Prozesse verkomplizieren. Schneidet man seine Services zu groß, kann das auf Kosten der Skalierbarkeit gehen. Man sollte sich deshalb im Voraus einige Gedanken machen, um sich seine Architektur hier nicht langfristig zu verbauen.
Ein wichtiges Risiko liegt allerdings auch in der Stabilität eines Systems. So hat der Ausfall einer einzelnen Komponente in einem verteilten System oft geringe oder gar keine Auswirkungen auf die anderen Komponenten. Ein monolithisches System fällt in einem solchen Fall oftmals komplett aus. Bei einem Shopsystem kann das einen großen Unterschied machen - funktioniert die Produktdetailseite und der Checkout weiterhin, so kümmert es die meisten Kunden wahrscheinlich weniger, wenn die digitalen Bedienungsanleitungen nicht verfügbar sind. Das hat eine direkte Auswirkung auf die Verfügbarkeit, da es in einem lebenden System - wie einem kontinuierlich weiterentwickelten Onlineshop - auch mit größter Vorsicht zu Problemen kommen wird.
Die Entscheidung für die passende Architekturform fällt nicht leicht, da jede mögliche Entscheidung ihre Vor- und Nachteile hat. Die erwartete Lebenszeit des Systems, der Umfang, aber auch die strategischen Anforderungen wie ein möglichst schneller Go-Live, sind beeinflussende Faktoren, die in Betracht gezogen werden müssen. Wer auf ein sauberes, zukunftssicheres Design setzen möchte und dafür möglicherweise bereit ist, Mehraufwand zu investieren, sollte sich zumindest Gedanken machen, welche Architektur die passende ist.
Wir glauben, dass sich heute, in einer Zeit schnell auftretender und wechselnder Anforderungen, eine Microservice Architektur oft bewähren kann. Die Entscheidungsfindung für den richtigen Architekturansatz ist jedoch deutlich komplexer, als man das auf den ersten Blick meinen mag.
Im letzten Artikel unserer kleinen Serie werden wir uns mit einer möglichen Migration von einem Monolithen hin zu einer Microservice Architektur beschäftigen.