Posted on Leave a comment

Microservices

Microservices

blank

Microservices sind ein Architekturmuster, das in den letzten Jahren an immer mehr Bedeutung gewonnen hat. Bei einer solchen Architektur geht es darum, Software in kleine, in sich abgeschlossene Dienste beziehungsweise Services zu unterteilen, die flexibel und unabhängig voneinander ausgetauscht und skaliert werden können. Das nutzen unter anderem Softwareriesen wie Amazon, Google und Netflix. Doch was sind Microservices im Detail und welche Vor- und Nachteile bringen sie mit sich?

Die Eigenschaften von Microservices

Der Begriff Microservices wurde stark von Martin Fowler geprägt. Nach seiner Definition beschreiben Microservice-Architekturen den Ansatz, Software in kleine, unabhängige Komponenten zu splitten. Jeder Service läuft in einem eigenen Prozess und die Interaktion erfolgt über leichtgewichtige Protokolle, beispielsweise REST (Representational State Transfer). Die Dezentralisierung aller die Architektur betreffenden Entscheidungen steht im Vordergrund. Weiterhin gilt für Microservices:

  • Sie können von einem kleinen Team implementiert und gewartet werden.
  • Ihr Umfang ist so gering, dass ein Service durch das Team mit niedrigem Zeitaufwand komplett neu geschrieben werden könnte.
  • Sie sind in sich abgeschlossen und erfüllen exakt eine klar definierte Aufgabe. Man bezeichnet dies als Bounded Context, ein Prinzip aus dem Domain-Driven Design. Bei Domain-Driven Design wird versucht, den Aufbau einer Software anhand von vorhandenen Fachbereichen (Domänen) zu strukturieren.
  • Sie haben ein klar definiertes Interface, verbergen aber jegliche Interna. Für alle anderen Services und Konsumenten ist jeder Microservice eine Blackbox.
  • Aus diesem Grund nutzt jeder Service auch eine eigene Datenbank und einen eigenen Prozess. Die Services müssen nicht einmal auf derselben Hardware laufen, um die Aufgabe der Software zu erfüllen.
  • Sie sind skalierbar und habe keine fest Adresse, unter sie angesprochen werden können. Ein Service kann daher nach Bedarf beliebig oft gestartet und ausgetauscht werden.
  • Sie sind zustandslos, speichern also keine Informationen über vorangegangene Anfragen, die die Ausführung der aktuellen Anfrage beeinflussen. Existieren mehrere Instanzen eines Services ist es egal, welche Instanz einen Prozessschritt ausführt.

Weitere Bestandteile einer Microservices-Architektur

Damit eine Microservice-Architektur funktioniert, sind neben den Services selbst weitere Bestandteile notwendig, die die nötige Infrastruktur bereitstellen. Wichtig sind dabei insbesondere Service Discovery und ein Gateway, das als Eintritt in die Architektur oder als Zwischenschicht zwischen den Services dient.

Service Discovery

Ein wichtiger Teil einer Microservice-Architektur ist Service Discovery, ein Mechanismus, durch den die einzelnen Dienste auffindbar sind. Es gibt einige Werkzeuge, mit denen Service Discovery aufgesetzt werden kann, denn eine eigene Implementierung kann schnell komplex werden. Grundsätzlich handelt es sich meist um ein Register mit fester Adresse, an der die Dienste sich registrieren, wenn sie verfügbar sind. Wird ein Dienst benötigt, kann über das Register eine aktuell gültige Adresse abgefragt werden.

API Gateway

Ein Gateway ist eine Art Zwischenschicht, die Anfragen durch einen Konsumenten, der durchaus ein Service selbst sein kann, entgegennimmt und entsprechend weiterleitet. Das Gateway übernimmt also die Funktion als Vermittler. Das hat den Vorteil, dass die innere Struktur darüber, welcher Service zu welchem Zweck mit welchem Service kommuniziert, verborgen wird. In dem Gateway können auch Service Discovery und Load Balancing – also das Verteilen vieler Anfragen, um einen Service nicht zu überlasten – integriert werden. Einer der größten Vorteile eines zentralen Gateway ist es, dass Sicherheitskriterien und Authentifizierung an einer Stelle geregelt werden können.

Vorteile von Microservices

Um die Vorteile von Microservices zu verstehen, muss man zuerst das „klassische“ Gegenstück kennen. Das Gegenstück zu einer Microservice-Architektur sind sogenannte monolithische Architekturen, die vor allem zu Beginn der Softwareentwicklung das häufigste Muster waren, nachdem Anwendungen umgesetzt wurden. Bei einem Monolithen wird die Software im ganzen programmiert, kompiliert, ausgeliefert und bei Bedarf geändert. Es gibt zwar zumeist mehrere Schichten, wie Datenschicht, Businesslogik und Nutzeroberfläche, doch diese hängen stark zusammen und können meist nicht unabhängig voneinander ausgetauscht werden. Insbesondere schnelle Release-Zyklen und flexible Anpassungen sind dadurch nicht möglich. Microservices ändern genau das.

Flexible Änderungen und kurze Release-Zyklen

Wird an einer monolithischen Architektur eine Komponente oder Anforderung geändert, kann das recht viele Nebeneffekte für andere Teile des Programms nach sich ziehen. Selbst, wenn der Monolith in sich gut designed ist und eine Änderung daher nur wenige Konsequenzen hat, muss der Monolith komplett neu gebaut und ausgeliefert werden damit die Änderung wirksam wird – ein bisweilen langwieriger Prozess. Sollen neue Features hinzugefügt und getestet werden, müssen für jedes Feature neue Builds erfolgen und alle Tests ausgeführt werden. Das kostet sehr viel Zeit, die man in der agilen Entwicklung eigentlich nicht in diesen Prozess investieren möchte.

Ändert sich hingegen die Anforderung an eine Microservice-Architektur, muss nur der Service, der in der entsprechenden Domäne liegt, angepasst und getestet werden. Lediglich bei einer Schnittstellenänderung kann es zu weitergehenden Änderungen kommen. Mittlerweile existieren  verschiedene Entwurfsmuster, mit denen solche Anpassungen leicht durchgeführt werden können.

Erweiterbarkeit

Oft kommt es vor, dass sich Anforderungen an eine Software nicht nur ändern, sondern sogar neue hinzukommen. Microservice-Architekturen sind sehr gut erweiterbar, denn ein neuer Service kann völlig ohne andere Abhängigkeiten geschrieben und in das System eingeführt werden. Müssen andere Services die neue Funktionalität konsumieren, funktioniert das über die Schnittstelle, sodass recht wenige Änderungen in bestehendem Code notwendig sind.

Flexible Skalierung

Betrachtet man beispielsweise ein Warenhaus, so gibt es dort viele einzelne Funktionen, die durch Dienste zur Verfügung stehen müssen: Warenabfragen, das Abwickeln von Verkäufen und Stornierungen oder das Accountmanagement sind nur einige davon. Bei hohen Lastsitzen, beispielsweise bei Sonderangeboten oder Schlussverkäufen, gibt es viele Anfragen zu Waren und zum Einkauf. Die Anfragen für Accountfunktionen oder Stornierungen steigen aber nicht proportional. Wäre die Software des Warenhauses ein Monolith, müsste die gesamte Software nach oben skaliert werden, um die Lastspitze zu bearbeiten. Das kostet Rechenressourcen für Funktionen, die eigentlich nicht benötigt werden. Wenn jeder Dienst in sich abgeschlossen ist und ohne Abhängigkeiten ausgeliefert oder gestartet werden kann, kann auch nur der Dienst, der benötigt wird, nach oben skaliert werden. Vor allem, wenn eine Software oder Webseite ständig verfügbar sein und solche Spitzen ausgleichen können soll, sind Microservices also geeignet.

Polyglot Programming

Als Polyglot Programming bezeichnet man das Nutzen eines diversen Technologie-Stacks – für jeden Teil der Software kann die Sprache oder Technologie gewählt werden, die für die jeweiligen Anforderungen am besten geeignet ist. Das ist bei Microservices möglich, da es keine Abhängigkeiten über die Schnittstellen hinaus geben sollte. Die Schnittstellen können in einer generischen Sprache wie JSON, SOAP oder XML definiert werden, sodass die dahinterliegende Implementierung für den Konsumenten nicht relevant ist. Ein Service in Java kann problemlos mit einem Dienst in Python oder C# kommunizieren.

Die Nutzung verschiedener Programmiersprachen hört sich gut an, kann aber auch zu Problemen führen, beispielsweise wenn man doch einmal eine stärkere Verknüpfung zwischen einzelnen Diensten braucht, deren Implementierungen nicht kompatibel sind.

Nachteile

Natürlich haben Microservices nicht nur Vor-, sondern auch Nachteile. Diese entstehen vor allem aus der erhöhten Komplexität und betreffen einige zentrale Aspekte der Softwareentwicklung.

Schwieriges Logging und Monitoring

Das Überwachen der einzelnen Services ist deutlich komplexer als das Überwachen eines Monolithen. Die Services können nicht in eine gemeinsame Logdatei schreiben, denn zum einen widerspricht das wichtigen Grundgedanken der Architektur, zum anderen müssen die Services nicht zwangsweise auf derselben Maschine laufen. Logdateien über das Netzwerk zu schreiben, kann wiederum teuer hinsichtlich der Laufzeit und Performanz sein. Schreiben die Services jeweils in eigene Logdateien ist es schwierig, Fehler korrekt zuzuordnen und Ereignisketten zu analysieren. Es gibt diverse Tools, die Logfiles aggregieren und auswerten, vor allem in Unternehmen, die bisher eher schlechte Logging-Praktiken haben, ist dieser Aspekt aber ein definitiver Fallstrick.

Notwendige Infrastruktur und Netzwerk

Microservices müssen nicht immer auf derselben Hardware laufen. Gerade, wenn die Services stark skaliert werden sollen, ist das auch oft gar nicht möglich. Entsprechend müssen die Services über ein Netzwerk miteinander kommunizieren. Insbesondere die Frage, wie die Services die Adresse eines anderen finden, sowie die Sicherheit und Netzwerkkapazität sind dabei komplexe Themen, über die man sich vor der Implementierung des ersten Services Gedanken machen sollte.

Erschwerte Testbarkeit

Ein weiterer Aspekt, der unter der erhöhten Komplexität einer Microservice-Architektur leidet, ist die Testbarkeit. Während sich jeder Service selbst durch Unit Tests gut testen lässt, sieht das für das Gesamtsystem oder die Interaktion mehrerer Services – um beispielsweise einen ganzen Prozess zu testen – schon anders aus. Häufig müssen Mock-Objekte, also Attrappen, die einen anderen Teil der Software repräsentieren, verwendet werden. Vor allem Aspekte wie Race Conditions – also mehrere Anfragen, die gleichzeitig bei einem Service eintreffen – oder das Verhalten bei langsamen Netzwerken, lassen sich aber selbst dann nur schwer in einer Testumgebung nachstellen.

Microservices im Zusammenhang mit anderen IT-Themen

Microservices haben Schnittstellen zu anderen hochaktuellen Themen der IT, insbesondere Cloud Computing, Continuous Integration / Continuous Delivery und Containerisierung.

  • Cloud Computing: Einer der größten Vorteile von Microservices ist die Möglichkeit, jeden Service nach Bedarf zu skalieren. Cloud Computing liefert die dazu nötigen Ressourcen on-demand. Dadurch müssen die Rechenressourcen, die man selbst für die höchste Skalierung benötigen würde, nicht mehr lokal vorgehalten werden
  • Continuous Integration (CI) / Continuous Deployment (CD): Als CI bezeichnet man den Prozess, Änderungen mehrere Nutzer regelmäßig in das gemeinsame Hauptprojekt zu integrieren. Je unabhängiger die Arbeit dabei ist, umso einfacher und reibungsloser verläuft dieser Prozess. CD erweitert dieses Vorgehen auf die Auslieferung der Software. So soll das Hauptprojekt stehts funktionsfähig sein und in kurzen Abständen ausgeliefert werden können. Beide Techniken zusammen sind essentiell für agile Entwicklung und kurze Feature- und Release-Zyklen
  • Containerisierung: Containerisierung ist eine Praktik, bei der eine Applikation in einer virtuellen Umgebung gestartet wird, die alle zur Ausführung benötigen Dateien und Laufzeitumgebungen bereitstellt. Der Unterschied zu einer klassischen virtuellen Maschine ist die geringere Größe, hohe Portabilität und die Geschwindigkeit, mit der die Container hochgezogen und wieder heruntergefahren werden können. Container sind für Microservices hervorragend geeignet: Sie enthalten alle Abhängigkeiten und Konfigurationen für die einzelnen Services und erleichtern damit die Skalierbarkeit und Auslieferung der Software.


Abgrenzung von Microservices zu SOA

Den Ansatz, eine Software modular aus einzelnen Diensten aufzubauen, gibt es schon seit einer Weile unter den Namen Serviceorientierte Architektur (SOA). Auch bei einer solchen Architektur gibt es verschiedene Komponenten, die miteinander über ein festgelegtes Protokoll kommunizieren. Einer der Hauptunterschiede zwischen beiden Ansätzen ist, dass für Microservice-Architekturen die Unabhängigkeit der einzelnen Dienste noch stärker im Vordergrund steht. Bei SOA sind die Services größer und können stärkere Abhängigkeiten besitzen. Hohe Skalierung und Continuous Integration / Deployment sind bei SOA entsprechend schwieriger umzusetzen.

Weiterhin nutzt SOA eine andere Grundarchitektur. Während hier für die Kommunikation meist ein Enterprise Service Bus genutzt wird, über den alle Services kommunizieren, gibt es eine solche fixe Entität in Microservice-Architekturen nicht. Auch die Datenhaltung kann zwischen den Diensten einer SOA-Software geteilt werden, während jeder Microservice seine eigene Datenhaltung nutzt, um die lose Kopplung noch stärker zu erzwingen.

Fazit

Microservices sind ein interessantes Architekturmuster, das klassischen monolithischen Architekturen entgegensteht. Die Software wird in kleine, in sich abgeschlossene Dienste unterteilt, die völlig unabhängig entwickelt, ausgetauscht und skaliert werden können und miteinander über leichtgewichtige Protokolle kommunizieren. Jeder Service erfüllt genau eine klar definierte Aufgabe. Das bringt viele Vorteile mit sich, beispielsweise eine größere Flexibilität bei neuen Anforderungen, Erweiterbarkeit, Skalierbarkeit und kurze Release-Zyklen. Vor allem Cloud Computing und Continuous Integration / Continuous Deployment sind daher Techniken, die eng mit Microservices zusammenhängen. Allerdings bringt die Aufsplittung der Gesamtsoftware in viele kleine Teile auch eine erhöhte Komplexität mit sich. Diese Komplexität erschwert vor allem das Logging und Monitoring zum Auffinden von Fehlern, die in einer Prozesskette auftreten, und verringert die Testbarkeit der Software.

Ähnliche Produkte

Schreibe einen Kommentar