Monolithische Architekturen
Monolithische Architekturen zeichnen sich dadurch aus, dass die gesamte Benutzeroberfläche, der Datenzugriff und die Verarbeitung in einer einzigen Anwendung bereitgestellt werden. Bei Code-Änderungen wird die gesamte Anwendung neu deployt.
Vor allem zu Beginn eines Projektes sind monolithische Architekturen deutlich einfacher zu verwalten und zu deployen. Das Deployment beschränkt sich auf ein Deploymentartefakt.
Die Codebasis für einen Monolithen befindet sich häufig an einem Ort. Somit ist die Erstellung einer API übersichtlich und zugehörige Funktionalität kann schnell gefunden werden. Dies vereinfacht auch das Debugging.
Das Testing von monolithischen Architekturen ist einfacher, da wir ein zu testendes Artefakt haben. Netzwerkverbindungen und umfangreiche Authentifizierungsmechanismen fallen somit im Testing weg.
Bekannte monolithische Anwendungen wie GitLab oder WordPress werden seit Jahrzehnten erfolgreich (weiter)entwickelt.
Doch natürlich gibt es auch einige Nachteile bei der Verwendung einer monolithischen Architektur.
Je größer eine monolithische Anwendung wird, desto mehr technische Schulden entstehen. Die Wartbarkeit wird hierdurch enorm erschwert und die Anwendung wird fehleranfälliger.
Die Skalierung bei monolithischen Architekturen ist nicht sehr effizient. Einzelne Komponenten der Anwendung können nicht skaliert werden.
Hat eine einzelne Komponente oder ein Modul einen Fehler, kann dies zum Ausfall der gesamten Anwendung führen.
Je größer die Anwendung wird, desto aufwändiger wird es Neuheiten oder Versionsupdates von Technologiekomponenten oder Programmiersprachen umzusetzen. Weiterhin ist der gesamte Monolith häufig in einer einzelnen Programmiersprache entwickelt, was die Effizienz beeinträchtigen kann (“Use the right tool for the right job“).
Nicht zuletzt führen schon kleine Anpassungen des Codes zu einem kompletten Redeployment, was sehr risikoreich sein kann.
Microservices sollen einige dieser Probleme adressieren.
Microservices
Microservices sind in sich geschlossene Komponenten, die eingeständig lauffähig sind und miteinander interagieren. Jeder Service erfüllt eine bestimmte Funktion und hat in der Regel eine eigene Datenhaltung und eine eigene Oberfläche.
Diese Eigenschaften bringen diverse Vorteile gegenüber einer monolithischen Architektur.
Die einzelnen Microservices können von unterschiedlichen Teams entwickelt werden, welche jeweils eigene Releasezyklen verfolgen können und unabhängig von einander ihren Microservice in Betrieb bringen können.
Hierdurch kann auch das Deployment von Kleinständerungen regelmäßiger durchgeführt werden. Netflix treibt dies mit einer Continous Deployment Pipeline auf die Spitze. Hier wird jede Änderung automatisiert bis in die Produktionsumgebung gebracht.
Jeder Microservice kann unabhängig von anderen Microservices skalieren. Dies ermöglicht eine höhere Effizienz bei der Ressourcennutzung und dadurch weniger Verschwendung und geringere Kosten.
Beim Testing kann jeder Microservice einzeln getestet werden. Die Wartbarkeit steigt, da die Komplexität innerhalb eines Microservices überschaubar ist. Außerdem ist es auch möglich einzelne Services komplett neu zu entwickeln.
Jeder Microservice kann die Technologien nutzen, die für das jeweilige Nutzungsszenario optimal sind. Das einzige Limit ist hierbei das Know-How des Teams.
Dadurch, dass Microservices nur eine bestimmte Funktion (z.B. Warenkorb) erfüllen, hat ein Ausfall eines Services nur einen Ausfall einer einzelnen Komponente zur Folge. Die restliche Anwendung bleibt weiterhin erreichbar.
Doch leider sind auch Microservice Architekturen nicht perfekt.
Durch die Eigenständigkeit und Unabhängigkeit der Teams kann die Technologiefreiheit zu einem Wildwuchs an Technologien führen.
Es kann außerdem dazu führen, dass das “Große Ganze” durch die Fokussierung auf wenige Services aus dem Blick gerät.
Bei der Verwendung von Microservices müssen auf organisatorischer Ebene neue Austauschformate entwickelt werden, um gemeinsam Standards, Zuständigkeiten und Schnittstellen zu definieren.
Wenn die Services komplett eigenständig betrieben werden fallen höhere Kosten für die Grundinfrastruktur an, wenn diese nicht mehr geteilt werden.
Microservices haben Abhängigkeiten untereinander. Es können Fehler bei der Netzwerkverbindung zwischen den Services auftreten. Einzelne Transaktionen verteilen sich über mehrere Microservices.
All dies führt dazu, dass Microservices schwer zu betreiben sind. Vor allem die Überwachung und Fehleranalyse kann eine Herausforderung werden.
Fazit
Abhängig von der Erfahrung des Betriebs- und Entwicklungsteams macht es durchaus Sinn bei einer Neuentwicklung erst mit einer monolithischen Architektur zu beginnen. Dies beschleunigt den Entwicklungsprozess und vereinfacht den Betrieb.
Der Monolith sollte jedoch so konzipiert sein, dass es im Nachhinein einfach ist einzelne Teile herauszulösen. Dies ermöglicht die schrittweise Überführung in eine Cloud-optimierte Architektur.
Hierdurch können die Vorteile aus beiden Architekturmustern genutzt werden.
Erfahrene Teams können durchaus schon mit einer reinen Microservice Architektur beginnen. Dies eignet sich vor allem bei größeren und erfahreneren Teams. Wichtig ist hierbei, dass die Services korrekt anhand der fachlichen Anforderungen zugeschnitten sind (Service Boundaries).
Mich interessiert Deine Meinung! Antworte gerne auf diesen Newsletter und teile mir mit, was dir gefallen hat, was dir gefehlt hat und was du dir für die Zukunft wünschst. Auch über fachlichen Input freue ich mich!
Leseempfehlungen
Bei weiterem Interesse empfehle ich die folgenden Artikel:
Why we’re sticking with Ruby on Rails von Sid Sijbrandij
Sid erklärt hier die Architekturentscheidungen hinter GitLab. Neben weiteren interessanten Einblicken wird hier auch diskutiert, warum GitLab keine Microservices Architektur nutzt.
MonolithFirst von Martin Fowler
Martin erklärt hier warum wir neue Projekte als Monolith starten sollten und nicht von Beginn an auf Microservices setzen sollten.