BLOG
Microservices – Architektur für servicegetriebene Geschäftsmodelle?
Seit geraumer Zeit in aller Munde: Microservices. Vor allen Dingen die Geschäftswelt soll davon profitieren. Volatile Märkte, neue alte Trends wie Cloud Computing, Big-Data, IoT etc. stellen Unternehmen vor Herausforderungen, die es schnell und erfolgreich zu bewältigen gilt.
Das Versprechen dieser Art der „kleinen Dienste“, der Microservices, besteht in einer ganz neuen Art von Dynamik in der Software-Entwicklung und im –Deployment, die durch Microservices möglich werden. Kurz und knapp: Sowohl die Geschäftswelt wie auch Anwender dürfen sich freuen – eröffnen sich durch Microservice-Architekturen doch ganz neue Chancen: Beschleunigte Entwicklungsmodelle, ein schnelleres Time-to-Market, ein Plus an Flexibilität, unabhängigere Teams etc. Und auf der Seite der Anwender entsteht eine neue, großartige Welt der Dienste und Apps. Buzzwords, Marketing-Bingo, Mantra oder Heilsversprechen? Was steckt hinter dem Paradigma der Microservices?
Was sind Microservices?
Ok, nähern wir uns der Antwort umgangssprachlich, schließlich wollen wir die Idee der Microservices einfach und nachvollziehbar erklären: Microservices stellen ein Architekturkonzept, ein Paradigma der Anwendungsentwicklung dar. Dabei geht es um die Art und Weise, wie Anwendungen entwickelt werden. Umfangreiche Anwendungssoftware, die konzeptuell über Microservices realisiert werden, besteht aus kleineren, voneinander unabhängigen Programmen. Jedes dieser Programme kümmert sich genau um eine Aufgabe – getreu der Unix-Philosophie: „Do one thing well.“ Eine für die Software-Welt recht erfolgreiche Philosophie, bewährt sie sich doch im Userland/Userspace in vielen Inkarnationen und Ausprägungen bis zum heutigen Tag – seit den frühen 70er Jahren, von den Unix-Ursprüngen und nachfolgenden BSDs über Nextstep und Darwin bis hin zu Linux.
Diese Programme kommunizieren als Microservices dann über wohl definierte APIs (Schnittstellen) miteinander. Da sich Schnittstellen im Idealfall gegenüber den verwendeten Programmiersprachen agnostisch verhalten, ermöglicht dies ebenfalls neue Spielräume für Entwicklungsteams. Gleichzeitig erzwingt das Microservices-Paradigma auch eine Unabhängigkeit der einzelnen Microservices voneinander. Das zeitigt Konsequenzen: Ein einzelner Microservice funktioniert dann unabhängig von allen anderen Services und Diensten, oder eben auch nicht. Macht nichts. Denn: Tritt letzterer Fall ein, bringt dieser Ausfall nicht alle anderen Services zum Stillstand. Das ist zwar unangenehm, aber gut genug. Ein Software-System, das konzeptionell aus vielen dieser Microservices besteht, lässt sich mit Recht eine Microservices-Architektur nennen.
Microservice vs. Monolith: der Unterschied metaphorisch verdeutlicht
Nähern wir uns der Angelegenheit mit einem Bild. Ebenso wie beim Hausbau gibt es eine Vielzahl von Möglichkeiten, wie IT-Systeme entworfen und gebaut sind. Daran lässt sich der Unterschied zwischen einem Microservice im Vergleich zu einem Monolithen sehr anschaulich verdeutlichen.
Der monolithische Ansatz
Man stelle sich zur Vereinfachung ein Ein-Familien-Haus vor: Je nach Bedarf kann der Architekt ein klassisches Haus in rechteckiger Form bauen Die Architektur ist starr, alles hat seinen festen, vorab definierten Platz. Fenster, Türen, Wände, Keller und Etagen… – ein monolithisches System, ein starres Gebilde. Will der Bewohner hier nach Jahren etwas ändern, dann steht er vor einer Vielzahl von Problemen: Kann ich zum Beispiel wirklich diese oder jene Wand einreißen oder im Dachgeschoss neue Wände und somit Räume für diverse Zwecke errichten – oder gefährde ich dann die Statik? In der Software-Entwicklung entspräche dieses Konzept dem Monolithen (s.u.)
Der Microservice-Ansatz
Ein Hausbesitzer kann sich aber auch von Anfang an für eine flexible, modulare Bauweise entscheiden. Eben in der Voraussicht, dass seine Bedürfnisse sich in Zukunft ändern werden. Im ersten Schritt überlegt der Bauherr sich, das Haus aus einzelnen Containern zu bauen. Schon während seiner Anfangsüberlegungen, fällt ihm ein, nicht auf quaderförmige Container zu setzen – sondern auf Container in einem hexagonalen Format, ähnlich der Waben eines Bienenstocks. Warum wird gleich klar. So kann er z. B. ein Haus aus hexagonalen Containern bauen, indem der Bauherr nicht nur weitere daneben und obendrauf stapelt. Vielmehr kann er später z.B. in der dritten Etage einfach auch einen Container wieder rausziehen, ohne dass die vierte oder fünfte Etage in Mitleidenschaft gezogen wird. Dieser Ansatz entspräche einer Microservices-Architektur.
Diese sehr simple Darstellung lässt sich auch auf IT- und Software-Systeme übertragen. Das klassische Haus entspräche in etwa der monolithischen Architektur, das Containerhaus der Microservice-Architektur. Beide besitzen Vor- und Nachteile.
Beispiele für Microservices – Arbeitsteilung konkret veranschaulicht
Nehmen wir die Website eines Paket- und Briefdienstes. Auf dieser Website stehen zahlreiche Microservice-Beispiele zur Verfügung:
- Sendungsverfolgung,
- Portoberechnung,
- Online-Frankierung,
- Wunschort zum Sendungsempfang etc.
Und all dies natürlich auch als Services für Privat- und Geschäftskunden. Und nur weil zum Beispiel die Sendungsverfolgung ausfällt, heißt das eben nicht, dass alle anderen Microservices in Mitleidenschaft gezogen werden und nicht mehr verfügbar sind. Diese Dienste stellen gute Beispiele für eine Microservice-Architektur dar. Viele der Dienste lassen sich z.B. über eine Rest-API ansprechen; natürlich lassen sich Microservices dann eben auch über eine App für iOS und Android benutzen. Dies sind allesamt Indizien, die auf eine Microservices-Architektur hinweisen könnten. Weitere praktische Microservices Beispiele kommen bei den Unternehmen Twitter, eBay, Spotify, Netflix und Zalando etc. zum Einsatz.
Monolithische Architekturen – traditionell aber nicht überholt
Um überhaupt Microservice-Architekturen zu verstehen, lohnt sich zunächst nochmals ein Blick auf klassische Architekturen. Deren Struktur kann man sich als eine einzige große Anwendung vorstellen, einen Block, in dem der gesamte notwendige Code gesammelt ist. Schlechterdings sind die bereitgestellten Funktionen zwar modularisiert, dabei weder voneinander unabhängig noch als unabhängig vom gesamten Block zu sehen. Den Monolithen gibt es nur en bloc. Fertiggeschrieben wird die Software und als Einheit kompiliert und „deployed“, das heißt auf Anwender PCs oder auf Servern verteilt. Jener wurde vor Jahren als monolithische Anwendung realisiert (300 bis 500 MB groß, Compile-Zeit bis zu 10 Std.). Nicht leicht zu warten und nicht ohne weiteres ließen sich neue Funktionen hinzufügen, vom Deployment ganz zu schweigen. Mehr zum Thema erfahren Sie im nachfolgenden Artikel: Microservices vs. Monolith.
Microservice Vorteile auf einen Blick
Sollten Flexibilität und Geschwindigkeit gegenwärtig in der Geschäftswelt von Bedeutung sein, kommt einer Microservice-Architektur eine besondere Rolle zu. Zwar sollte der initiale Aufwand, eine Microservice-Architektur zu planen, zu entwickeln und schließlich auszurollen, nicht unterschätzt werden. Jener ist mit Sicherheit höher als im Vergleich zu einer monolithischen Applikation. Aber: Steht die Architektur erst einmal, lassen sich viele Microservice-Vorteile ausspielen. Dann stellt es ein Unternehmen eben nicht mehr vor Probleme, z.B. neue Geschäftsideen “einfach mal“ auszuprobieren.
So wäre es dann ohne Weiteres möglich, Geschäftsideen oder Ziele über sogenannte „minimum viable products“ (MVPs) beschleunigt einem ersten Realitätstest zuzuführen. Darin liegt einer der Microservice-Vorteile. Gleiches gilt für darauffolgende, schnelle Iterationen von Fehlerkorrekturen, Anpassungen und Verbesserungen des ersten MVPs als Microservice – ideal für serviceorientierte Architekturen. Aber dies ist eben nur einer der Microservice-Vorteile. Schauen wir uns an, was Microservices noch an Vorteilen bieten und warum dies so ist.
Microservice – vielgestaltige Unabhängigkeit
Zentrale Merkmale, Eigenschaften und schließlich Vorteile der Microservices wie auch einer Microservices-Architektur bestehen in deren Unabhängigkeit und zwar in verschiedener Hinsicht.
Technologische Wahlfreiheit 1: Microservices REST-Api
In welcher Programmiersprache ein Client geschrieben wird, der mit dem Microservice interagiert, steht zur freien Wahl. Da Anfragen oft über eine REST-API(REpresentational State Transfer) entgegengenommen werden, kann clientseitig jede Programmiersprache benutzt werden, die REST beherrscht. REST basiert auf den HTTP-Verben GET, PUT, POST/PATCH wie auch DELETE und ist sehr altes Netzwerkprotokoll. So hat man für die Clients, was die Programmiersprache angeht, die Wahl. Denn ob ein Client für einen Microservice Python basiert ist oder in einer beliebig anderen Sprache, spielt keine Rolle, solange der Client REST beherrscht und die REST-API ansprechen kann. Die Entscheidung über die Frage, in welcher Programmiersprache ein Client für einen Microservice geschrieben wird, hängt dann von anderen Gesichtspunkten ab.
Mit welchen Protokollen lassen sich Microservices clientseitig noch ansprechen?
REST stellt sicherlich nicht die einzige API/Protokoll dar, mit dem Microservices vom Client aus angesprochen werden können. Einige der nun folgenden Beispiele sind an REST angelehnt, erweitern diese und eignen sich für Microservices:
- Open Data Protocol (oDATA): Ein aus dem Hause Microsoft stammendes, ebenfalls HTTP-basiertes Protokoll
- WebSockets: Für Kommunikation in real-time, durch persistente Verbindung zwischen Client und Service, ohne HTTP-Overhead und Verzicht auf “long-polling”
- GraphQL: Anfrage- und API-Beschreibungssprache, eingeführt von Facebook
- RESTful API Modeling Language (RAML): Beschreibungssprache von APIs und deren Verwendung
- OpenAPI Specification: Standard zur Beschreibung REST-konformer APIs; vorangetrieben durch die OpenAPI Initiative
Technologische Wahlfreiheit 2: Unabhängigkeit der gewählten Programmiersprache
Selbst bei der Implementierung von Microservices besteht ein Plus an Freiheit. Prinzipiell kann jeder Microservice in einer anderen Programmiersprache implementiert sein. Die Entscheidung darüber muss im jeweiligen Team getroffen werden, dass den Microservice implementieren und betreuen wird. Sicherlich sind dazu wichtige Vorüberlegungen notwendig. Wichtig zu wissen: Nur auf diesem Wege ermöglicht und erhält man die Unabhängigkeit und Flexibilität der Microservices und schafft die Voraussetzungen für ein beschleunigtes Deployment von Microservices (siehe dazu auch Docker).
Wie kommunizieren eigentlich Microservices untereinander?
Nachdem der Client Daten via REST an einen Microservice übermittelt hat, stellt sich die Frage, was passiert nun damit? Innerhalb einer Microservice-Architektur liegt es ziemlich nahe, dass die Daten untereinander ebenfalls über an REST angelehnte APIs kommuniziert werden.
ne Kommunikation der verschiedenen Microservices untereinander – kurz: auf ASYNC abzustellen – sollte dabei stets das Ziel sein. Ohne an dieser Stelle in Details zu gehen, bedeutet asynchrone Kommunikation an dieser Stelle, dass z.B. Microservice A seinen Call an Microservice B absetzt – ohne auf das Resultat dieser Anfrage zu warten. . A “weiß” nun, dass seine Anfrage angekommen ist und sich darum gekümmert wird – mit der Folge, dass bei A Ressourcen freibleiben und weitere Vorteile entstehen, wie z.B. eine geringere Latenz innerhalb der Microservices-Architektur. Als Protokolle kommen dann zum Beispiel die folgenden zum Einsatz:
- RESTful (s.o.)
- OData (s.o.)
- Google Remote Procedure Calls (gRPC)
- Remote Procedure Calls (RPC)
- Thrift
Der Einsatz von Message Queues, gewissermaßen ein eigener Nachrichtendienst, z.B. mit RabbitMQ oder Kafka, treibt diesen ASYNC-Gedanken auf die Spitze. Bei RabbitMQ wird z.B. mit speziellen Nachrichten-Protokoll. Auch dazu bestehen verschiedene Ansätze. Das Wichtigste dazu vorab: Eine asynchrolen (AMQP, MQTT, STOMP) gearbeitet. Hier werden Korrelations-IDs verwendet, um zu verfolgen, welche Antwortnachricht sich auf welche Anfrage bezieht.
Unabhängiges Deployment der Microservices
Im Idealfall besteht aufgrund vorheriger Überlegungen und Entscheidungen nun die Option, einen Microservice unabhängig von allen anderen Diensten der Microservice-Architektur auszurollen. Damit sind die zentrale Stärken und Eigenschaften eines Microservice beschrieben. Eben weil sich ein Microservice nur um eine Aufgabe kümmert, besitzt er idealerweise eine vergleichsweise kleine Code-Basis, ist im Vergleich schnell ausgerollt, gestartet – und dieser Dienst beeinflusst zudem keinen anderen Dienst der Microservices-Architektur. Alle anderen Microservices bleiben während des Deployments verfügbar, müssen nicht neu deployt werden. Um im oben erwähnten Beispiel zu bleiben, kann der Kunde weiterhin seine Sendungen frankieren, obwohl der Microservice zur Sendungsverfolgung gerade neu ausgerollt wird.
Dieser Ansatz eignet sich also perfekt für eine serviceorientierte Architektur. Wichtig zu wissen: Diese Aufteilung der Microservices spiegelt sich auch in den Verantwortlichkeiten der Teams wider. So können DevOps-Teams gebildet werden, die jeweils auf einen ganz bestimmten Microservice spezialisiert sind – das „Do one thing well“ gilt dann eben auch für die Teams (siehe: DevOps)
Im Vergleich zu einem monolithisch konzipierten System werden die Vorteile einer Microservice-Architektur offensichtlich: Ist der Monolith einmal in Betrieb, müssen bei Änderungen entsprechende Wartungszeiten eingeplant werden. Denn aufgrund der Struktur ist stets das ganze System betroffen und muss gegebenenfalls mehrfach neu gestartet werden, um zu testen, ob die Änderungen im Code auch den gewünschten Effekt haben. Dies entfällt durch eine Microservice-Architektur. Gerade diese Neustarts illustrieren ein weiteres Problem monolithischer Strukturen: Je häufiger die Veränderungen und je größer die Code-Menge, desto langsamer der Entwicklungsprozess – und häufige Veränderungen sind sehr erwünscht, wenn es um den Einsatz von bspw. MVPs via Microservices geht.
Microservices: Skalierbarkeit fein und granular
Mit der beschriebenen Segmentierung lassen sich neben dem unabhängigen Deployment jedoch noch andere Vorteile der Microservice-Architektur erzielen. Einmal bspw. via Docker (s.u.) ausgerollt, stellt es die Teams vor keine größeren Herausforderungen, sich um die Skalierbarkeit der einzelnen Dienste zu kümmern. Gesetzt den Fall, dass ein Microservice in Übermaßen die CPU-Zeit in Anspruch nimmt oder zu viel Speicher alloziert, lässt sich dies recht zügig über einen Load-Balancer und über einen zusätzlichen Microservice ausgleichen. Bei einem Monolithen muss das System manuell immer in seiner Gesamtheit skaliert werden.
Alles eingepackt: Microservices mit Docker
Einmal in schmale Docker-Container verpackt, steht dem raschen Deployment einzelner Microservicnehmenskultur.es nichts mehr im Weg. Durch die Verbreitung und die Begeisterung für Microservice-Architekturen hat sich im Laufe der letzten Jahre eine Toolchain für den Prozess der Softwareauslieferung entwickelt.
Verschiedene Technologien stehen den Teams der einzelnen Microservices dafür zur Verfügung. Deren Ziel: Den Deployment-Prozess weitgehend zu automatisieren und damit zu vereinfachen. Zeit sparen, Fehler vermeiden ist die Devise.
Docker und Kubernetes
Bei der Komplexität von Services, die eine Microservices-Architektur aufweisen können, benötigt das DevOps-Team natürlich die passenden Werkzeuge zur Administration. Kubernetes (K8s) ist eines davon. Man stelle sich nur die Ausgangssituation vor: Die Basis der Architektur besteht aus vielen Docker-Containern und zahlreichreichen Hosts, also einzelnen physischen oder virtuellen Rechnern. Durch Kubernetes lassen sich nun die Docker-Container gruppieren, in Pods zusammenfassen und z.B. auf einem Node (Vhost oder physischer Rechner) ausrollen. Kubernetes Vorteile liegen hier im vergleichsweise einfachen und schnellen Deployment der Microservices. Gleichzeitig bietet K8s eine komfortable Lösung, um eine Microservice-Architektur mit z.B. hunderten Microservices zu managen: Lastspitzen auszugleichen, zu skalieren und zu monitoren. Dashboards (WebUI) und diverse Kommandozeilenprogramme stellen dabei die Werkzeuge der Wahl dar, um die Services dann On-Premises, Hybrid oder in der Public Cloud zu managen – perfekt für DevOps-Dirigenten zur Orchestrierung der Microservices. (Kubernetes ist Open-Source (Apache License 2.0))
Jede neue Iteration eines Microservice kann dann mit den Fehlerbehebungen und neuen Erweiterungen zügig, mit geringem Risiko und wenig manuellem Aufwand in die Staging- oder Produktivumgebung eingepflegt werden. Selbst für diesen Bereich der Software-Entwicklung bedient man sich neuer Methoden und Team-Strukturen und Verantwortlichkeiten, gewissermaßen auch einer neuen Unternehmenskultur.
Was ist Docker?
Docker zählt zu einer leichtgewichtigen Virtualisierungslösung. Zentrales Element von Docker sind Container. Innerhalb dieser Docker-Container lassen sich alle zu einem Microservice gehörenden Bestandteile (Code, Systemwerkzeuge und -bibliotheken etc.) in einem IMG-File verpacken. Durch Docker-Container werden die auf einem Rechner genutzten Ressourcen sauber getrennt. Als Container nutzt die Virtualisierungslösung den Kernel des Hosts und bringt im Gegensatz zu VirtualBox, VMware oder XEN keinen eigenen Kernel / kein eigenes Betriebssystem mit. Weniger RAM- und Zeitverbrauch zum Start von Microservices sind die Konsequenz.
Trio Infernale: Continuous Delivery, Devops und Microservices
Damit aus einem hehren Ziel auch Realität entsteht, hat es sich als Best-Practice erwiesen, auf DevOps-Teams und die Methode Continuous Delivery zu setzen. In Kombination mit Microservices stellt dieses Trio ein Kind seiner Zeit dar- Stichworte „Volatile Märkte/neue Herausforderungen für Unternehmen/schnelle Bereitstellung stabiler Dienste“. Warum lassen die eben angerissenen Anforderungen und Ziele gerade durch dieses Trio der Microservices, DevOps und Continuous Delivery erreichen?
Das Kunstwort DevOps besteht aus der Zusammensetzung der Kurzformen von „Dev“ für Development und „Op“ für Operations – hier: für den IT-Betrieb. Softwareentwicklung und Systemadministration und das Deployment von Microservices werden nunmehr zusammengedacht. Eine enge Zusammenarbeit von Entwicklung und Betrieb zum Zweck der schnellen Bereitstellung reibungslos funktionierender Microservices ist das Ziel. DevOps-Teams haben ihre Expertise sowohl in der Software-Entwicklung UND in punkto IT-Systeme und System-Infrastruktur. In DevOps vereint sich also das Beste zweier Welten. Zusammengebracht mit der Methode Continuous Delivery bedient sich DevOps dabei einer Werkzeug-Kette, bestimmter Techniken und Prozesse, die das Software-Deployment automatisiert und optimiert – hinsichtlich Software-Qualität, Flexibilität und Geschwindigkeit.
Releasing software is too often an art; it should be an engineering discipline
David Farley
Microservices revisited – der heilige Gral?
Natürlich lauert das Problem oft im Detail. Und sicherlich erscheint es auf den ersten Blick vielversprechend, durch die Implementierung von Microservices zur Lösung unternehmerischer Anforderungen, zu einem servicegetriebenen Geschäftsmodell zu kommen. Allerdings hängt vieles von der konkreten Situation, der Problemstellung und Zielsetzung ab, ob eine Microservice-Architektur überhaupt sinnvoll sein kann. An dieser Stelle deshalb noch als Fazit eine kurze Gegenüberstellung der Vor- und Nachteile der Microservice-Architekturen:
Vorteile von Microservice-Architekturen
- Eine kleinere Codebasis bedeutet eine geringere Komplexität innerhalb der einzelnen Microservice
- Der Kommunikationsaufwand zwischen den einzelnen Projektteams wird verringert
- Continuous Delivery
- Bessere Skalierbarkeit: Es lassen sich einzelne Services mehrfach skalieren
- Hohe Ausfallsicherheit
Nachteile von Microservice-Architekturen
- Komplexität des gesamten Systems der Microservices
- Anspruchsvolles Deployment der Dienste
- Unerwartete Latenz zwischen den Microservices im verteilten System
- Jeder Microservice stellt ein unabhängiges System dar; das gilt auch für den Deployment-Prozess; Ressourcen müssen vorgehalten werden; kostenintensiv
- Hoher Aufwand bei der Migration von Alt-Systemen in die neue Microservice-Architektur