Pragmatische Ansätze bei Microservices-Architekturen
Wen man heutzutage jemanden fragt, wie moderne (Enterprise-)Software-Entwicklung aussieht, dann wird man mit sehr hoher Wahrscheinlichkeit folgende Punkte aufgezählt bekommen:
- Natürlich wird agil gearbeitet, bevorzugt nach SCRUM.
- Bei der Backend-Architektur sind Microservices mittlerweile Common-Sense, Monoliten gelten als veraltet.
- Das Frontend ist eine Single-Page-Application, die per REST mit dem Backend kommuniziert.
- Und betrieben wird alles in einer PaaS, entweder in der Cloud oder notfalls doch on-premise.
- ( ... )
Dieses Bild ist relativ verbreitet, das zeigt uns auch ein Blick in Fachzeitschriften und Konferenzen, wo diese Themen seit Jahren prominenter Bestandteil der Agenda sind. Dies hat auch auf viele Unternehmen abgefärbt, die sich als Ziel gesetzt haben, ihre komplette Software-Entwicklung in diese Richtung zu transformieren, weil sie sich davon höhere Effizienz versprechen.
Cargo Cults
Die Beweggründe für den Wunsch nach dieser Transformation klingen allerdings, wenn man sie genau hinterfragt, oft dogmatisch. So als wenn all die aufgezählten Punkte ausschließlich Vorteile hätten und es somit nur folgerichtig wäre, sich dorthin entwickeln zu wollen. Nur leider gibt es Silver-Bullets, wie Architekturstile, Technologien und Prozesse, die ausschließlich Vorteile haben, nicht wirklich. Je nach Produkt welches man baut und den Bedingungen, unter welchen man im Unternehmen Software entwickelt, ergeben manche Ansätze durchaus Sinn. Manche nur in abgewandelter Form. Und manche gar nicht. Im Gegenteil, sie richten massiven Schaden an, wenn man sie falsch anwendet. Der Vergleich mit Cargo-Cults1, der oft verendet wird, um dieses Phänomen zu beschreiben, trifft den Nagel auf den Kopf.
Pragmatismus
Was hilft dagegen? Hinterfragen von Prozessen und Entscheidungen. Eine genaue Analyse von Vor- und Nachteilen. Eine grundsätzliche Offenheit für Veränderungen. Aber auch eine gesunde Resistenz gegen Hypes. Kurz gesagt: Pragmatismus.
Diese Artikelserie ist als allgemeines Plädoyer für mehr Pragmatismus in der Software-Entwicklung zu verstehen. Dass wir pragmatischer in unserer Entscheidungsfindung werden und uns Fragen stellen, weshalb wir etwas Neues einführen, welches bestehende Problem wir damit eigentlich lösen und ob das dann auch tatsächlich zum Unternehmen passt. Nur weil Netflix auf Microservices schwört und Spotify mit seinem Vorgehensmodell effizient ist, bedeutet das noch nicht automatisch, dass man deren Ansätze 1:1 übernehmen kann und ähnliche Effekte erzielen wird.
Wir werden uns in den nächsten Beiträgen gezielt das Thema Microservices ansehen und einen vom Hype befreiten Blick auf Theorie und Praxis werfen.
Microservices - immer eine gute Idee?
Eine Definition, was Microservices sind, werden wir überspringen. Schnell im Web gesucht, findet man hunderte Definitionen, aus denen man sich seine Favorisierte auswählen darf. Ein vernünftiger Ansatz, wo anstatt einer Definition gemeinsame Charakteristika herangezogen werden, kommt von Martin Fowler2.
Pro und Contra
Aber was verspricht man sich im Allgemeinen von Microservices? Richtig angewandt, bieten sie zweifelsfrei viele Vorteile:
- Sie sind das Resultat einer konsequent durchgezogenen Modularisierung, was allgemein als Qualitätsmerkmal einer Systemarchitektur gesehen werden kann.
- Die Komplexität eines Microservice ist schon alleine aufgrund der Dimensionen wesentlich kleiner und deswegen sind diese leichter zu verstehen.
- Sie sind voneinander physisch entkoppelt und können unabhängig deployt und aktualisiert werden, ohne dass man das Gesamtsystem dafür neu deployen muss.
- Aufgrund der physikalischen Trennung sind microservice-basierte Systeme resilienter, da z.B. ein Speicherleck oder Überlastung nur ein Service beinträchtigt und nicht das ganze System.
- Die Skalierbarkeit vom Gesamtsystem wird verbessert, da die Last in der Regel nicht auf alle Services gleich verteilt ist und man somit nur die stark beanspruchten hochskalieren muss.
- Microservices werden von nur einem Team entwickelt, womit die Freiheit erhöht und das Konfliktpotential reduziert wird.
- Jedes Service kann in der für seinen Anwendungsfall optimalen Sprache und Technologie umgesetzt werden. Technologie-Upgrades werden leichter umsetzbar, da sich diese nur auf einzelne Services beschränken.
- Durch klar definierte Schnittstellen ist eine Wiederverwendbarkeit der Services gegeben.
Dem gegenübergestellt werden in der Regel eine Handvoll Nachteile, die vor allem hervorheben, dass man an vielen Stellen mit höheren Aufwänden rechnen muss:
- Integrationstests sind im Setup wesentlich aufwendiger, weil diese nun mehrere Services involvieren, die in der richtigen Version instanziert werden müssen.
- Logging wird aufwendiger, da die Logs von mehreren Services aggregiert werden müssen um den Kontext eines Fehlers zu rekonstruieren.
- Feingranulares Monitoring im Betrieb ist Pflicht, um Ausfälle bzw. Überlastungen von einzelnen Services erkennen und dem entgegensteuern zu können.
- Die Komplexität des Systems wird nur von den einzelnen Services zum "Integrationslayer" verschoben, seien dies nun andere (higher-level) Services, eine Prozessengine oder ein Message-Bus/-Broker.
Es gibt jedoch auch zahlreiche versteckte Herausforderungen, welche sich erst richtig bemerkbar machen, wenn man bereits in einer microservices-typischen Sackgasse gelandet ist:
- Die an sich sinnvolle Regel, dass jedes Service die Hohheit über die eigene Daten(bank) hat und diese niemals mit anderen Services direkt teilen sollte, hat als Konsequenz dass es wesentlich schwieriger wird, Daten aus mehreren Quellen zu aggregieren (keine direkten Joins möglich) oder Updates transaktional zu machen.
- Refactorings werden aufwendiger. Zwar nicht die innerhalb eines einzelnen Services, aber wenn man zur Erkenntnis kommt, dass der Serviceschnitt nicht optimal ist und man gerne Services zusammenführen/aufteilen/transformieren will, dann ist die Komplexität dieses notwendigen Refactorings wesentlich höher, da Logik und vor allem Daten zwischen zwei de-facto unabhängigen Modulen migriert werden müssen. (Sorgt für schönen Nervenkitzel in der Produktion!)
- Die Kompatibilität zwischen Schnittstellen und Clients muss gewährleistet sein. Das bedeutet, dass Schnittstellen immer abwärtskompatibel sein müssen oder, dass bei manchmal unvermeidlichen Breaking Changes, ein neues Service erschaffen werden muss.
- Das Management der Versionierung von Services, inklusive automatisiertem Check, ob Abwärtskompatibilität gewährleistet ist oder wie lange welche Versionen von welchen Services in Verwendung sind, ist nicht trivial.
- Der Betrieb wird wesentlich komplexer, da nun eine Vielzahl von Services in der korrekten Version deployt, aktualisiert, überwacht und dynamisch skaliert werden muss.
- Durch die Aufteilung eines Systems in mehrere Services, entstehen zumindest auf Transportebene neue Fehlerquellen, denen man mit Relisienzpatterns entgegenwirken muss.
Fazit
Prinzipiell könnte man die Liste an Vorteilen, Nachteilen und Falltüren, die es zu beachten gibt, noch weiter fortführen. Gewiss hat jedes Team, welches Microservices anwendet eigene positive und negative Erfahrungen gemacht, die es dieser Diskussion beisteuern könnte. Die Quintessenz ist jedoch, dass die Entscheidung, Microservices zu machen, kein No-Brainer ist und gründlich durchdacht werden sollte. Nicht alles, was bei Netflix, Amazon, etc. gut funktioniert, wird automatisch auch im eigenen Unternehmen erfolgreich einsetzbar sein. Was auch - vor allem im Enterprise-Umfeld - oft übersehen wird, ist dass eine erfolgreiche Microservice-Architektur nicht nur die Technik umfasst, sondern dass die gesamte Organisation der Unternehmens darauf ausgerichtet sein muss, um auch wirklich die Vorteile ausspielen zu können.
In dieser Artikelserie, werden wir uns diverse Aspekte daraus genauer ansehen. Am Anfang werden wir uns passenderweise das Bootstrapping eines Microservice-Systems ansehen und die Frage beleuchten, ob es sinnvoll ist dieses bereits von Tag eins an zu modularisieren, oder ob es auch andere Wege gibt.
- Die Cargo-Kult-Wissenschaft: https://de.wikipedia.org/wiki/Cargo-Kult-Wissenschaft↩↩↩
- Martin Fowler über Microservices bei der GOTO 2014: https://www.youtube.com/watch?v=wgdBVIX9ifA↩↩↩