Schein und Sein

Was sind eigentlich Microservices?

Eberhard Wolff

© iStockphoto.com/pixonaut

Kaum ein Thema ist im Moment so ein Hype wie Microservices. Welche Gründe gibt es dafür? Und wie kann man Microservices gewinnbringend einsetzen? Welche Herausforderungen gibt es? In diesem Artikel gibt Eberhard Wolff einen Überblick über den Architekturtrend und beantwortet die wichtigsten Fragen.

Was sind Microservices?

Die wesentliche Eigenschaft von Microservices ist das unabhängige Deployment.

Microservices dienen eigentlich nur zur Modularisierung von Software. Für Modularisierung gibt es aber unzählige Ansätze: Klassen, Packages oder JARs dienen in der Java-Welt beispielsweise diesem Ziel. Nur so können auch große Projekte in kleine Einheiten aufgeteilt werden und bleiben dadurch erweiterbar und wartbar. Aber Microservices sind anders: Die wesentliche Eigenschaft von Microservices ist das unabhängige Deployment. Ein Microservice kann in Produktion gebracht werden, ohne dass die anderen Microservices ebenfalls neu deployt werden müssen.

Während also bei den klassischen Deployment-Monolithen die Module wie Klassen, Packages oder JARs alle gleichzeitig in Produktion gebracht werden müssen, ist das bei Microservices nicht so. Übrigens können Deployment-Monolithen durchaus intern sauber modularisiert sein – nur müssen eben alle Module gemeinsam in Produktion gebracht werden.

Konkret können Microservices beispielsweise als einzelne Docker-Container umgesetzt sein. Mehrere solcher Container bilden dann zusammen eine Anwendung. Jeder einzelne Microservice kann eine REST-Schnittstelle haben oder für bestimmte URLs die Weboberfläche als HTML-Seiten erzeugen.

Durch die Aufteilung in mehrere Deployment-Einheiten wie Docker-Container ergeben sich neben dem unabhängigen Deployment noch verschiedene andere Konsequenzen: Jeder Microservice kann in einer anderen Programmiersprache auf einer anderen Plattform implementiert sein. In einem Docker-Container kann schließlich fast jede Infrastruktur laufen. Ebenso kann jeder Microservice einzeln skaliert werden. Dazu sind nur ein Load Balancer und mehrere Instanzen des Docker-Containers notwendig. Auch bezüglich der Robustheit ist ein Microservice eine Einheit: Wenn beispielsweise ein Microservice zu viel Speicher allokiert oder die CPU stark belastet, beeinflusst das nur diesen einen Microservice. Wenn die anderen Microservices sogar den Ausfall dieses Microservice tolerieren können, entsteht so ein sehr robustes System.

Es gibt auch ganz andere Infrastrukturen für Microservices. Beispielsweise erlaubt Amazon Lambda [5] das Deployment einzelner in Java, JavaScript oder Python geschriebener Funktionen. Diese werden auch automatisch in ein Monitoring integriert. Die Abrechnung erfolgt pro Aufruf, wobei die erste Million Aufrufe kostenlos ist.

Lesen Sie auch: Java EE trifft Microservices: Elefant im Porzellanladen?

Eine solche Technologie verringert den Aufwand für einen Microservice erheblich: Er muss nur mit einem Kommandozeilenwerkzeug deployt werden, den Rest erledigt die Infrastruktur. Es ist also kein Aufbau eines Docker-Containers oder ähnliches notwendig. Solche Technologien können die Nutzung von Microservices erheblich vereinfachen. Dennoch bieten sie eine gute Isolation und eine gute Skalierbarkeit einzelner Services. Microservices müssen also nicht unbedingt Docker nutzen – im Gegenteil, andere Ansätze wie Amazon Lambda können sogar noch einfacher und effizienter sein.

Die drei Microservice-Varianten

Am Ende entstehen aber durch Microservices ein verteiltes System und viel zusätzliche Komplexität. Es muss also gute Gründe geben, warum man Microservices nutzt. Ein radikales Beispiel für Microservices ist Fred Georges Developer Anarchy [2]. Alle Mitglieder der Teams entwickeln – es gibt also auch keine Requirements Engineers oder Manager. Das Ziel der Entwickler sind die Geschäftsziele – also beispielsweise ein höherer Umsatz. Erfahrungen mit diesem Ansatz gibt es sowohl in modernen Umgebungen wie Internetanzeigen aber auch in klassischen Organisationen wie dem Onlinemagazin des Guardian. Typische Microservices sind in diesem Szenario sehr klein – 10 oder 100 Zeilen Code sind durchaus im Bereich des Möglichen. Jeder der Microservices kann beispielsweise einen Teil eines Algorithmus für die Platzierung von Anzeigen implementieren. Die Microservices sind in verschiedenen Programmiersprachen geschrieben, und es ist sogar denkbar, einen Microservice in einer anderen Programmiersprache neu zu schreiben. Die Entscheidung dazu treffen die Entwickler. Die Microservices kommunizieren asynchron – und über diesen Kanal können sie auch Log- und Monitoringdaten bereitstellen.

Netflix steht für einen anderen Ansatz: Die Microservices implementieren REST-Schnittstellen, die von den Clients genutzt werden können. Ziel ist nicht nur eine unabhängige Entwicklung der Microservices, sondern auch eine Skalierung der Microservices. Für die Implementierung setzt Netflix primär auf Java. Die meisten Werkzeuge und Bibliotheken aus dem Netflix-Universum sind auf diese Programmiersprache abgestimmt. Diese Tools stehen als Open Source zur Verfügung. Andere Technologien sind zwar auch möglich – aber nur über einen Sidecar. Er ist in Java geschrieben und stellt die Funktionalitäten über eine REST-Schnittstelle zur Verfügung. Die Microservices sind wesentlich größer und implementieren komplexere Geschäftsfunktionalitäten.

Ein weiterer Ansatz sind Self-contained Systems (SCSs) [3]. Jedes SCS ist eine eigene Webanwendung. Sie können Daten replizieren oder auch Logik in einem anderen SCS aufrufen, aber der Schwerpunkt des Ansatzes liegt auf der Integration von Webinhalten. Im einfachsten Fall sind das Links auf ein anderes SCS, aber es können auch HTML-Schnipsel anderer SCSs integriert werden (Transklusion). Ein SCS ist typischerweise in der Verantwortung eines Teams und kann intern in mehrere Microservices aufgeteilt sein. SCSs können auch außerhalb von Microservices ein guter Ansatz sein, um die Arbeit mehrerer Teams bei der Entwicklung von Portalen zu koordinieren. Da der Fokus auf einer Integration der Web-Frontends liegt, muss bei der Nutzung von SCSs auch auf diesen Bereich ein Hauptaugenmerk liegen.

Bildschirmfoto 2016-05-23 um 09.29.35

Tabelle 1: Microservices-Ansätze im Vergleich

Gründe für Microservices

Microservices erlauben es, die technische Koordination auf ein Mindestmaß zu reduzieren.

Wie schon erwähnt, gibt es für Microservices viele unterschiedliche Gründe – die unabhängige Skalierung oder auch die Robustheit zählen dazu. Ein weiterer Grund ist sicher auch, dass gerade Java-Anwendungen dazu neigen, in zu großen Deployment-Einheiten ausgeliefert zu werden. Wenn die Startzeit einer Anwendung eine viertel oder halbe Stunde dauert, ist das zu viel. Solche Anwendungen könnten zwar sauber strukturiert sein, aber sie sind oft unübersichtlich. Eine Aufteilung in Microservices erzwingt eine strikte Trennung. Bestandteile anderer Microservices können nur über die Schnittstelle genutzt werden, und dazu ist entsprechender Code notwendig. Es schleichen sich also nicht einfach so Abhängigkeiten ein, sondern sie müssen explizit ermöglicht und eingeführt werden. Das gewährt auch langfristig eine gute Strukturierung der Software.

Wenn man sich jedoch die Nutzung von Microservices in der Praxis anschaut, so ist ein Grund besonders wichtig: Die größere technische Unabhängigkeit erlaubt auch ein unabhängiges Arbeiten der Teams. Wenn jedes Team an getrennten Microservices arbeitet, kann jedes Team einen eigenen Technologiestack nutzen, die Anwendungen unterschiedlich deployen und monitoren. Nur wenige Entscheidungen müssen übergreifend getroffen werden: Die Integration der Microservices muss einheitlich sein – sei es mit REST, Messaging, einer Webintegration wie beim SCS-Ansatz oder mit Datenbankreplikation.

Lesen Sie auch: Modularität für Microservices: Es lebe das Modul!

Auch ohne Microservices ist schon ein recht unabhängiges Arbeiten möglich: Wenn jedes Team an eigenen fachlichen Anforderungen arbeitet und an einer eigenen fachlichen Komponente, ist die Entwicklung scheinbar unabhängig möglich. Eine solche fachliche Aufteilung mit einer klaren Zuordnung von Fachlichkeiten zu bestimmten Teams und einer Aufteilung der Architektur nach fachlichen Aspekten bekommt durch Microservices gerade mehr Aufmerksamkeit – aber eigentlich war es schon immer ein sinnvoller Ansatz für die Architektur.

Aber selbst wenn die Fachlichkeiten in jeweils einer Komponente angesiedelt sind und auch Änderungen nur eine solche Komponente betreffen: Es ist dennoch eine gemeinsame technische Koordination notwendig. Schließlich muss der gesamte Deployment-Monolith eine einheitliche technische Basis haben. Im Falle von Java müssen die exakten Versionen aller Bibliotheken festgelegt werden. Ebenso müssen die Releases koordiniert werden: Der Stand aller Module muss zusammenpassen, und jedes Modul muss eine Qualität haben, die für ein Release in Produktion ausreichend ist. Also können Fachlichkeiten unabhängig entwickelt werden, aber die Arbeit der Teams ist durch die enge technische Verzahnung in dem Deployment-Monolithen immer noch nicht unabhängig. (Abb. 1).

Microservices

Abb. 1: Deployment-Monolithen erzwingen technische Entscheidungen und Releases über das gesamte System

Microservices erlauben es, die technische Koordination auf ein Mindestmaß zu reduzieren. Dabei können Makro- und Mikroarchitektur unterschieden werden. Die Makroarchitektur umfasst alle Entscheidungen, die im Gesamtprojekt getroffen werden und dann für alle Microservices verpflichtend sind. Die Mikroarchitektur umfasst alle Entscheidungen, die jeder Microservice einzeln treffen kann. Nur wenige Entscheidungen gehören zwingend zur Makroarchitektur: beispielsweise der Integrationsansatz. Die Programmiersprache, die Plattform und auch das Deployment sowie Monitoring können in jedem Microservice anders gelöst sein. Natürlich sind das Optionen: Es gibt wohl kaum einen Vorteil, wenn jeder Microservice andere Werkzeuge für Deployment und Monitoring nutzt, aber der Aufwand für den Betrieb der Gesamtplattform steigt. Ebenso kann die technische Basis beispielsweise auf Java eingeschränkt werden, aber jeder Microservice kann nun ohne größere Probleme ein Bugfix-Release einer Library in Produktion bringen, ohne dass dazu eine Koordination mit anderen Teams notwendig wäre. Ebenso kann beispielsweise das Testen der einzelnen Microservices unterschiedlich gelöst werden.

wolff2

Abb. 2: Microservices isolieren technische Entscheidungen

Durch das Festlegen der Makroarchitektur kann jedes Projekt entscheiden, wie viel Freiheiten die Teams auf technischer Ebene haben sollen. Microservices ermöglichen es erst, solche Freiheiten zu schaffen. Da Microservices in der Umsetzung aufwendiger als andere Architekturansätze sind, ist es sinnvoll, den Teams möglichst viele Freiheiten zu geben.

Und natürlich ist es ohne Weiteres möglich, jeden Microservice einzeln in Produktion zu bringen. Das ergänzt die unabhängigen fachlichen Features sehr gut: Das Team kann sie nicht nur entwickeln, sondern auch in Produktion bringen. Also ist die Koordination bezüglich Releases wie auch bezüglich Technologien auf jeweils einen Microservice beschränkt (Abb. 2).

Beyond the Hype

Der Erfolg von Microservices ist auch gleichzeitig ein Problem.

Paradoxerweise ist der Erfolg von Microservices auch gleichzeitig ein Problem. Microservices werden sicher in Zukunft bei vielen Projekten genutzt werden, weil sie die übliche Architektur sind. Das ist problematisch, weil Microservices wie alle Architekturen ein Trade-off sind. Neben den schon erwähnten Vorteilen gibt es auch Herausforderungen – wenn man nicht sogar das Wort Problem dafür nutzen will.

Schon die Unabhängigkeit der Teams ist eine Herausforderung: Microservices können nur die technischen Voraussetzungen für eine größere Unabhängig schaffen. Aber tatsächliche die Unabhängigkeit zu ermöglichen, erfordert entsprechende organisatorische Änderungen. Die Teams müssen die dafür notwendigen Kompetenzen bekommen – und das bedeutet einen Machtverlust von Managern oder teamübergreifenden Architekten. Das ist nicht immer einfach umzusetzen. Ebenso bedeutet es, dass die Teams nicht nur mehr Freiheiten bekommen, sondern auch mehr Verantwortung übernehmen müssen. Es ist eben nicht mehr damit getan, dass sich das Team an die Vorgaben einer zentralen Architektur und engen technischen Regeln hält, sondern sie müssen selbst die Entscheidungen treffen, am Ende auch mit den Konsequenzen leben und für die Ergebnisse gerade stehen.

Lesen Sie auch: Microservices im Experten-Check: Wie groß sollte ein Microservice sein?

Auch auf technischer Ebene gibt es ebenfalls Herausforderungen: Viel mehr deploybare Einheiten müssen in Produktion gebracht und überwacht werden. Die Anzahl solcher Einheiten in einem Microservices-Projekt kann durchaus vergleichbar mit der Anzahl der Deployment-Einheiten aus allen klassischen Projekten in einer Organisation sein. Das alleine kann für eine IT-Abteilung schon kaum zu lösen sein. Hinzu kommt dann aber noch, dass die Services für die verschiedenen Testphasen deployt werden müssen. Das macht eine Automatisierung von Deployment und Test zwingend erforderlich – aber genau in diesen Bereichen haben viele Organisationen noch Nachholbedarf.

Es gibt auch einige nicht so offensichtliche Herausforderungen: So muss neben der Software selbst auch der Test passend modularisiert sein. Es ist nicht ausreichend, wenn Microservices einzeln in Produktion gebracht werden können, aber durch einen gemeinsamen Integrationstest de facto schon beim Test eine Koordination notwendig ist. Jede Änderung muss in einer Integration mit allen anderen Microservices getestet werden. Durch diese Phase kann jede Änderung nur alleine gehen, denn sonst ist bei einem Fehler nicht klar, welcher Microservice verantwortlich ist. Wenn beispielsweise ein solcher Test eine Stunde dauert, gibt es pro Tag nur acht Durchläufe durch die Tests – bei acht Teams also genau einen pro Team. Also kann ein Team genau einmal pro Tag einen Microservice ändern. Hier gilt es, Maßnahmen zu ergreifen, die den Integrationstest entlasten – beispielsweise Consumer-driven-Contract-Test.

Microservices bringen fundamentale Änderungen

In bestimmten Bereichen gehen Microservices ganz anders mit Architektur um als klassische Entwürfe. Beispielsweise ist ein Ziel von Microservices, dass jeder einzelne Service ersetz werden kann – beispielsweise durch eine Neuimplementierung. Normalerweise ist das kein Aspekt, der bei einer Architektur relevant ist. Im Fokus steht eher die Änderbarkeit der einzelnen Teile als ihre Ablösung. Warum sollte man auch bei dem Entwurf eines Microservice darauf achten, dass er am Ende durch etwas anderes ersetzt wird? Es erscheint logischer, den Microservice so aufzubauen, dass er auch langfristig den Anforderungen genügt. Aber viele Projekte und Entwickler beschäftigen sich damit, alte Systeme durch neue Implementierungen abzulösen. Daher ist die Idee, die Ablösung einer Software gleich schon beim Entwurf zu beachten, sicher ein wichtiger neuer Aspekt, den Microservices in den Mittelpunkt rücken.

Ebenso verstehen Microservices Organisation und Architektur als zwei Seiten einer Medaille. Das Gesetz von Conway [4] beschreibt genau diesen Umstand: Eine Organisation kann nur solche Architekturen hervorbringen, die ihren Kommunikationsbeziehungen entspricht. Dieses Gesetzt ist von 1968, hat aber erstaunlich wenig Konsequenzen auf die Architekturarbeit. Bei Microservices wird eine fachliche Aufteilung durch eine passende Aufteilung in die Teams und damit in der Organisation unterstützt. Es wird also nicht einfach hingenommen, dass die Organisation zu bestimmten Architekturen führt, sondern die gewünschte Architektur wird durch die Aufteilung in Teams weiter unterstützt. Auch das ist bei klassischen Architekturen als Ansatz kaum bekannt.

Schließlich unterstützen Microservices die unabhängige Arbeit von Teams. Letztendlich wird durch die Architektur sichergestellt, dass auch ein großes komplexes Gesamtsystem entwickelt werden kann. Dazu wird das große System in technisch unabhängige Systeme unterteilt. So wird letztendlich ein großes Projekt in viele kleine Projekte unterteilt. Dadurch können Probleme bezüglich der Skalierung der Organisation eines Projekts durch eine geschickte Architektur gelöst werden. Die Skalierung von Projekten wird üblicherweise auf der organisatorischen Ebene angegangen. Microservices lösen es durch technische Maßnahmen und die Architektur – auch das eine interessante Herangehensweise.

Also beschreiten Microservices bei der Ersetzbarkeit von Komponenten, der Äquivalenz von Organisation und Architektur sowie der Skalierung von Prozessen neue Wege. Auch wenn man nicht Microservices machen möchte, sollte man dennoch diese neuen Wege in der Softwarearchitektur für eigene Projekte evaluieren und gegebenenfalls nutzen.

Fazit

Microservices bieten eine andere Art der Modularisierung und haben wie jeder Architekturansatz Vor- und Nachteile. Der wichtigste Vorteil ist die unabhängige Arbeit der Teams. Allerdings ist gerade der Aufwand für den Betrieb, das Deployment und das Monitoring höher. Microservices können erhebliche Vereinfachungen und Vorteile zur Folge haben – und gerade bei großen Projekten sind sie oft eine sehr sinnvolle Alternative. Aber wenn die Herausforderungen nicht beachtet werden, wird die Umsetzung nicht zu den gewünschten Erfolgen führen. Und es muss auch eine für das Projekt geeignete Spielart der Microservices ausgewählt werden. Auf jeden Fall ist es nicht sinnvoll, Microservices einfach so zu nutzen, weil das eben der aktuell trendige Architekturansatz ist.

Eine etwas weitergehende Einführung findet sich im kostenlosen Microservices-Buch [6] oder auch in anderer Literatur [1].

Mehr zum Thema:

Microservices: Agilität mit Architektur skalieren

Geschrieben von
Eberhard Wolff
Eberhard Wolff
Eberhard Wolff ist Fellow bei innoQ und arbeitet seit mehr als fünfzehn Jahren als Architekt und Berater, oft an der Schnittstelle zwischen Business und Technologie. Er ist Autor zahlreicher Artikel und Bücher, u.a. zu Continuous Delivery und Microservices und trägt regelmäßig als Sprecher auf internationalen Konferenz vor. Sein technologischer Schwerpunkt sind moderne Architektur- und Entwicklungsansätze wie Cloud, Continuous Delivery, DevOps, Microservices und NoSQL.
Kommentare
  1. Konstantin Kauz2016-05-24 12:46:52

    Sehr geehrter Herr Wolff,

    mit Technologien wie OSGI muss man beispielsweise nicht die komplette Anwendung deployen.

    Auch solche Aspekte wie System übergreifende Transaktionen oder komplexere Testbarkeit werden nicht angerissen.

    Versions-Management der Services ist eine große Herausforderung

    Zu MicroServices gehört viel mehr als nur aufteilen einer monoliten Anwendung/Architektur. Vielmehr ist ein Rundumschlag notwendig, angefangen mit der Infrastruktur. Nur eine Kombination mit Technologien wie Cloud Foundry bzw. Anpassung der Test Pyramide an die Systemübergreifende Paradigmen führt zu erfolg.

    Somit eine schöne theoretische Aufarbeitung des Themas mit wenig Bezug zur Realität!

    Grüße,
    Konstantin Kauz

  2. Eberhard Wolff2016-05-31 15:29:19

    Hallo Herr Kauz,

    vielen Dank für das Feedback!
    - Zum Trade-Off für OSGi würde ich Ihnen einen Blick auf http://de.slideshare.net/ewolff/nanoservices-and-microservices-with-java empfehlen.
    - Zu Testbarkeit findet sich in dem Artikel ja ein Absatz und in meinem Buch über Microservices ein ganzes Kapitel.
    - Ebenso gehe ich im Buch auf Transaktionen und Versionen ein.

    Ich stimme Ihnen zu, dass Tests und Betrieb bzw. Plattformen entscheidende Herausforderungen sind. Das Fazit des Artikel erwähnt ja auch, dass es einige Herausforderungen gibt.

    Gruß,

    Eberhard Wolff

  3. Christian2017-03-07 01:04:42

    Schöner Artikel.
    Ein Punkt fehlt mir noch: Performance
    Zwar hat man im Netflix Stack schon den Cache umsonst obendrauf, aber letztendlich tauscht man einen Methodenaufruf gegen einen Http Request. Das das nicht nur die Komplexität erhöht, sondern auch einen großen Unterschied im Laufzeitverhalten macht ist mir ein bisschen untergegangen.
    Daher sollte man sich vorher sehr gut überlegen, ob man wirklich Microservices braucht und es nicht einfach verwenden weil es trendy ist.

    Grüße,
    Christian

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.