image
image

Eberhard Wolff arbeitet seit mehr als 15 Jahren als Architekt und Berater – oft an der Schnittstelle zwischen Business und Technologie. Er ist Fellow bei der innoQ. Als Autor hat er über hundert Artikel und Bücher geschrieben – u. a. über Continuous Delivery – und als Sprecher auf internationalen Konferenzen vorgetragen. Sein technologischer Schwerpunkt liegt auf modernen Architekturansätzen – Cloud, Continuous Delivery, DevOps, Microservices oder NoSQL spielen oft eine Rolle.

image

Zu diesem Buch – sowie zu vielen weiteren dpunkt.büchern – können Sie auch das entsprechende E-Book im PDF-Format herunterladen. Werden Sie dazu einfach Mitglied bei dpunkt.plus+:

www.dpunkt.plus

Eberhard Wolff

Microservices

Grundlagen flexibler Softwarearchitekturen

2., aktualisierte Auflage

image

Eberhard Wolff

eberhard.wolff@gmail.com

Lektorat: René Schönfeldt

Copy-Editing: Sandra Gottmann (Münster-Nienberge)

Satz: Nadine Thiele

Herstellung: Susanne Bröckelmann

Umschlaggestaltung: Helmut Kraus, www.exclam.de

Bibliografische Information der Deutschen Nationalbibliothek

Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über http://dnb.d-nb.de abrufbar.

ISBN:

Print978-3-86490-555-1

PDF978-3-96088-413-2

ePub978-3-96088-414-9

mobi978-3-96088-415-6

2., aktualisierte Auflage 2018

Copyright © 2018 dpunkt.verlag GmbH

Wieblinger Weg 17

69123 Heidelberg

Die vorliegende Publikation ist urheberrechtlich geschützt. Alle Rechte vorbehalten. Die Verwendung der Texte und Abbildungen, auch auszugsweise, ist ohne die schriftliche Zustimmung des Verlags urheberrechtswidrig und daher strafbar. Dies gilt insbesondere für die Vervielfältigung, Übersetzung oder die Verwendung in elektronischen Systemen.

Es wird darauf hingewiesen, dass die im Buch verwendeten Soft- und Hardware-Bezeichnungen sowie Markennamen und Produktbezeichnungen der jeweiligen Firmen im Allgemeinen warenzeichen-, marken- oder patentrechtlichem Schutz unterliegen.

Alle Angaben und Programme in diesem Buch wurden mit größter Sorgfalt kontrolliert. Weder Autor noch Verlag können jedoch für Schäden haftbar gemacht werden, die in Zusammenhang mit der Verwendung dieses Buches stehen.

5 4 3 2 1 0

Inhaltsverzeichnis

1Vorwort

1.1Überblick über Microservices

1.2Warum Microservices?

Teil IMotivation und Grundlagen

2Einleitung

2.1Überblick über das Buch

2.2Für wen ist das Buch?

2.3Übersicht über die Kapitel

2.4Essays

2.5Pfade durch das Buch

2.6Danksagung

2.7Änderungen in der 2. Auflage

2.8Links & Literatur

3Microservice-Szenarien

3.1Eine E-Commerce-Legacy-Anwendung modernisieren

3.2Ein neues Signalsystem entwickeln

3.3Fazit

Teil IIMicroservices: Was, warum und warum vielleicht nicht?

4Was sind Microservices?

4.1Größe eines Microservice

4.2Das Gesetz von Conway

4.3Domain-Driven Design und Bounded Context

4.4Self-contained Systems

4.5Fazit

4.6Links & Literatur

5Gründe für Microservices

5.1Technische Vorteile

5.2Organisatorische Vorteile

5.3Vorteile aus Geschäftssicht

5.4Fazit

5.5Links & Literatur

6Herausforderungen bei Microservices

6.1Technische Herausforderungen

6.2Architektur

6.3Infrastruktur und Betrieb

6.4Fazit

6.5Links & Literatur

7Microservices und SOA

7.1Was ist SOA?

7.2Unterschiede zwischen SOA und Microservices

7.3Fazit

7.4Links & Literatur

Teil IIIMicroservices umsetzen

8Architektur von Microservice-Systemen

8.1Fachliche Architektur

8.2Architekturmanagement

8.3Techniken zum Anpassen der Architektur

8.4Microservice-Systeme weiterentwickeln

8.5Microservice und Legacy-Anwendung

8.6Event-driven Architecture

8.7Technische Architektur

8.8Konfiguration und Koordination

8.9Service Discovery

8.10Load Balancing

8.11Skalierbarkeit

8.12Sicherheit

8.13Dokumentation und Metadaten

8.14Fazit

8.15Links & Literatur

9Integration und Kommunikation

9.1Web und UI

9.2REST

9.3SOAP und RPC

9.4Messaging

9.5Datenreplikation

9.6Schnittstellen: intern und extern

9.7Fazit

9.8Links & Literatur

10Architektur eines Microservice

10.1Fachliche Architektur

10.2CQRS

10.3Event Sourcing

10.4Hexagonale Architekturen

10.5Resilience und Stabilität

10.6Technische Architektur

10.7Fazit

10.8Links & Literatur

11Testen von Microservices und Microservice-Systemen

11.1Warum testen?

11.2Wie testen?

11.3Risiken beim Deployment minimieren

11.4Tests des Gesamtsystems

11.5Legacy-Anwendungen mit Microservices testen

11.6Tests einzelner Microservices

11.7Consumer-Driven Contract Test

11.8Technische Standards testen

11.9Fazit

11.10Links & Literatur

12Betrieb und Continuous Delivery von Microservices

12.1Herausforderungen beim Betrieb von Microservices

12.2Logging

12.3Monitoring

12.4Deployment

12.5Steuerung

12.6Infrastrukturen

12.7Fazit

12.8Links & Literatur

13Organisatorische Auswirkungen der Architektur

13.1Organisatorische Vorteile von Microservices

13.2Alternativer Umgang mit dem Gesetz von Conway

13.3Spielräume schaffen: Mikro- und Makro-Architektur

13.4Technische Führung

13.5DevOps

13.6Schnittstelle zu den Fachbereichen

13.7Wiederverwendbarer Code

13.8Microservices ohne Organisationsänderung?

13.9Fazit

13.10Links & Literatur

Teil IVTechnologien

14Beispiel-Implementierung von Microservices

14.1Fachliche Architektur

14.2Basistechnologien

14.3Build

14.4Deployment mit Docker

14.5Docker Machine

14.6Docker Compose

14.7Service Discovery

14.8Routing

14.9Resilience

14.10Load Balancing

14.11Integration anderer Technologien

14.12Tests

14.13Weitere Beispiele

14.14Fazit

14.15Links & Literatur

15Technologien für Nanoservices

15.1Warum Nanoservices?

15.2Definition Nanoservice

15.3Amazon Lambda

15.4OSGi

15.5Java EE

15.6Vert.x

15.7Erlang

15.8Seneca

15.9Fazit

15.10Links & Literatur

16Wie mit Microservices loslegen?

16.1Warum Microservices?

16.2Wege zu Microservices

16.3Microservice: Hype oder Realität?

16.4Fazit

Index

1Vorwort

Microservices sind ein neuer Begriff – aber sie verfolgen mich schon lange. 2006 hielt Werner Vogels (CTO, Amazon) einen Vortrag auf der JAOO-Konferenz, wo er die Amazon Cloud und Amazons Partnermodell vorstellte [1]. Dabei erwähnte er das CAP-Theorem – heute Basis für NoSQL. Und dann sprach er von kleinen Teams, die Services mit eigener Datenbank entwickeln und auch betreiben. Diese Organisation nennen wir heute DevOps und die Architektur Microservices.

Später sollte ich für einen Kunden eine Strategie entwickeln, wie er moderne Technologien in seine Anwendung integrieren kann. Nach einigen Versuchen, neue Technologien direkt in den Legacy-Code zu integrieren, haben wir schließlich eine neue Anwendung neben der alten Anwendung mit einem völlig anderen modernen Technologie-Stack aufgebaut. Die neue und die alte Anwendung waren nur über HTML-Links gekoppelt – und über die gemeinsame Datenbank. Bis auf die gemeinsame Datenbank ist auch dieses Vorgehen im Kern ein Microservices-Ansatz. Das war 2008.

Ein anderer Kunde hatte schon 2009 seine komplette Infrastruktur in REST-Services aufgeteilt, die jeweils von einzelnen Teams weiterentwickelt wurden. Auch das nennen wir heute Microservices. Viele andere Unternehmen aus dem Internet-Bereich hatten damals schon ähnliche Architekturen.

In letzter Zeit wurde mir außerdem klar, dass Continuous Delivery [2] Auswirkungen auf die Software-Architektur hat. Auch in diesem Bereich haben Microservices viele Vorteile.

Und das ist der Grund für das Buch: Microservices sind ein Ansatz, den einige schon sehr lange verfolgen; darunter auch viele sehr erfahrene Architekten. Wie jeder Architekturansatz löst er sicher nicht alle Probleme – aber er kann eine interessante Alternative darstellen.

1.1Überblick über Microservices

Microservice: vorläufige Definition

Im Mittelpunkt des Buchs stehen Microservices – ein Ansatz zur Modularisierung von Software. Modularisierung ist nichts Neues. Schon lange werden große Systeme in kleine Module unterteilt, um Software einfacher zu erstellen, zu verstehen und weiterzuentwickeln.

Das Neue: Microservices nutzen als Module einzelne Programme, die als eigene Prozesse laufen. Der Ansatz basiert auf der UNIX-Philosophie. Sie lässt sich auf drei Aspekte reduzieren:

Der Begriff Microservice ist nicht fest definiert. Kapitel 4 zeigt eine genauere Definition. Als erste Näherung dienen folgende Kriterien:

Dieser Ansatz betrachtet die Größe des Microservice nicht. Trotz des Namens »Microservice« ist die Größe für eine grobe Definition nicht so entscheidend.

Monolithen

Microservices grenzen sich von Deployment-Monolithen ab. Ein Deployment-Monolith ist ein großes Software-System, das nur als Ganzes auf einmal deployt werden kann. Es muss als Ganzes durch alle Phasen der Continuous-Delivery-Pipeline wie Deployment, Test, Abnahme und Release laufen. Durch die Größe des Deployment-Monolithen dauert dieser Prozess länger als bei kleineren Systemen. Das reduziert die Flexibilität und erhöht die Kosten der Prozesse. Der Deployment-Monolith kann intern modular aufgebaut sein – nur müssen alle diese Module gemeinsam in Produktion gebracht werden.

1.2Warum Microservices?

Microservices dienen dazu, Software in Module aufzuteilen und dadurch die Änderbarkeit der Software zu verbessern.

image

Abb. 1–1Vorteile von Microservices

Microservices haben einige wesentliche Vorteile:

Starke Modularisierung

Leichte Ersetzbarkeit

Nachhaltige Software-Entwicklung

Legacy-Anwendung erweitern

Time-to-Market

Unabhängige Skalierung

Technologiefreiheit

Continuous Delivery

Alle diese Gründe sprechen für die Einführung von Microservices. Welche Gründe am wichtigsten sind, hängt von dem Szenario ab. Die Skalierung agiler Prozesse und Continuous Delivery sind oft aus einer Geschäftssicht wichtig. Kapitel 5 widmet sich den Vorteilen von Microservices im Detail und geht auch auf die Priorisierung ein. Wo so viel Licht ist, ist auch Schatten. Daher wird Kapitel 6 noch detailliert darlegen, welche Herausforderungen bei der Umsetzung von Microservices existieren und wie man mit ihnen umgehen kann. Im Wesentlichen sind das die folgenden:

Beziehungen sind versteckt.

Refactoring ist schwierig.

Fachliche Architektur ist wichtig.

Betrieb ist komplex.

Verteilte Systeme sind komplex.

[1]http://jandiandme.blogspot.com/2006/10/jaoo-2006-werner-vogelscto-amazon.html

[2]Eberhard Wolff: Continuous Delivery: Der pragmatische Einstieg, dpunkt.verlag, 2014, ISBN 978-3864902086

Teil I

Motivation und Grundlagen

Dieser Teil des Buchs zeigt, was Microservices sind, warum Microservices so interessant sind und wo sie gewinnbringend genutzt werden können. So wird an praktischen Beispielen klar, was Microservices in welchen Szenarien bewirken.

Kapitel 2 erläutert die Struktur des Buchs. Um die Bedeutung von Microservices zu illustrieren, enthält Kapitel 3 konkrete Szenarien für die Nutzung von Microservices.

2Einleitung

In diesem Kapitel steht das Buch selber im Mittelpunkt: Abschnitt 2.1 beschreibt kurz das Konzept des Buchs, Abschnitt 2.2 beschreibt die Zielgruppe und Abschnitt 2.3 gibt einen Überblick über die Kapitel und Struktur des Buchs. Abschnitt 2.4 erläutert die Bedeutung der Essays im Buch. Abschnitt 2.5 beschreibt Pfade durch das Buch für die verschiedenen Zielgruppen und Abschnitt 2.6 enthält schließlich die Danksagung.

Errata, Links zu den Beispielen und weitere Informationen finden sich unter http://microservices-buch.de/.

2.1Überblick über das Buch

Das Buch gibt eine ausführliche Einleitung in Microservices. Dabei stehen die Architektur und Organisation im Mittelpunkt, ohne dass technische Umsetzungsmöglichkeiten vernachlässigt werden. Ein vollständig implementiertes Beispiel für ein Microservice-System zeigt eine konkrete technische Umsetzung. Technologien für Nanoservices zeigen, dass es sogar noch kleiner als Microservices geht. Das Buch vermittelt alles, um mit dem Umsetzen von Microservices loszulegen.

2.2Für wen ist das Buch?

Das Buch wendet sich an Manager, Architekten und Techniker, die Microservices als Architekturansatz einführen wollen.

Manager

Entwickler

Architekten

Im Buch gibt es Hinweise für eigene Experimente und Möglichkeiten zur Vertiefung. So kann der Interessierte das Gelesene praktisch ausprobieren und sein Wissen selbstständig erweitern.

2.3Übersicht über die Kapitel

Teil I

Der erste Teil des Buchs zeigt die Motivation für Microservices und die Grundlagen der Microservices-Architektur. Das Kapitel 1 hat schon die grundlegenden Eigenschaften, Vor- und Nachteile von Microservices erläutert. Kapitel 3 zeigt zwei Szenarien für den Einsatz von Microservices: eine E-Commerce-Anwendung und ein System zur Verarbeitung von Signalen. Dieser Teil vermittelt einen ersten Einblick von Microservices und zeigt auch schon Anwendungskontexte.

Teil II

Teil II erläutert nicht nur Microservices genauer, sondern beschreibt auch die Vor- und Nachteile:

Teil III

Im Teil III geht es um die Umsetzung von Microservices. Der Teil zeigt, wie die Vorteile aus Teil II erreicht werden und wie die Herausforderungen gelöst werden können.

Teil IV

Der letzte Teil des Buchs zeigt, wie Microservices ganz konkret technisch umgesetzt werden können. Dort geht es dann hinunter bis auf die Code-Ebene:

2.4Essays

Das Buch enthält Essays, die Microservices-Experten geschrieben haben. Die Aufgabe war, auf ungefähr zwei Seiten wichtige Erkenntnisse zu Microservices festzuhalten. Manchmal ergänzen die Essays das Buch, manchmal beleuchten sie andere Themen und manchmal widersprechen sie auch dem Rest des Buchs. Es gibt eben bei Software-Architekturen oft keine klaren Antworten, sondern verschiedene Meinungen und Möglichkeiten. Die Essays bieten die Chance, verschiedene Standpunkte kennenzulernen, um sich dann eine eigene Meinung zu bilden.

2.5Pfade durch das Buch

Das Buch bietet für jede Zielgruppe passende Inhalte (siehe Tab. 2–1). Natürlich kann und sollte jeder auch Kapitel lesen, die vielleicht nicht zur eigenen Rolle gehören. Aber der Fokus der Kapitel liegt auf der jeweiligen Rolle.

Kapitel

Entwickler

Architekten

Manager

3 – Microservice-Szenarien

X

X

X

4 – Was sind Microservices?

X

X

X

5 – Gründe für Microservices

X

X

X

6 – Herausforderungen bei Microservices

X

X

X

7 – Microservices und SOA

 

X

X

8 – Architektur von Microservice-Systemen

 

X

 

9 – Integration und Kommunikation

X

X

 

10 – Architektur eines Microservice

X

X

 

11 – Testen von Microservices und Microservice-Systemen

X

X

 

12 – Betrieb und Continuous Delivery von Microservices

X

X

 

13 – Organisatorische Auswirkungen der Architektur

 

 

X

14 – Beispiel-Implementierung von Microservices

X

 

 

15 – Technologien für Nanoservices

X

X

 

16 – Wie mit Microservices loslegen?

X

X

X

Tab. 2–1 Pfade durch das Buch

Wer nur an dem groben Inhalt eines Kapitels interessiert ist, kann das Fazit des Kapitels lesen. Wer direkt ganz praktisch einsteigen will, sollte mit den Kapiteln 14 und 15 anfangen, bei denen konkrete Technologien und Code im Mittelpunkt stehen.

Die Anleitungen zu eigenen Experimenten in den Abschnitten »Selber ausprobieren und experimentieren« können die Basis zu einer selbstständigen Vertiefung des Gelernten sein. Wenn ein Kapitel besonders wichtig erscheint, kann man die Aufgaben dazu durcharbeiten, um die Themen des Kapitels genauer kennenzulernen.

2.6Danksagung

Alle, mit denen ich das diskutiert habe, die Fragen gestellt oder mit mir zusammengearbeitet haben – viel zu viele, um sie alle zu nennen. Der Dialog hilft sehr und macht Spaß!

Besonders erwähnen möchte ich Jochen Binder, Matthias Bohlen, Merten Driemeyer, Martin Eigenbrodt, Oliver B. Fischer, Lars Gentsch, Oliver Gierke, Boris Gloger, Alexander Heusingfeld, Christine Koppelt, Andreas Krüger, Tammo van Lessen, Sascha Möllering, André Neubauer, Till Schulte-Coerne, Stefan Tilkov, Kai Tödter, Oliver Wolf und Stefan Zörner

Eine wichtige Rolle hat auch mein Arbeitgeber, die innoQ, gespielt. Viele Diskussionen und Anregungen meiner Kollegen finden sich in diesem Buch.

Schließlich habe ich meinen Freunden, Eltern und Verwandten zu danken, die ich für das Buch oft vernachlässigt habe – insbesondere meiner Frau.

Und natürlich gilt mein Dank all jenen, die an den in diesem Buch erwähnten Technologien gearbeitet und so die Grundlagen für Microservices gelegt haben.

Last but not least möchte ich dem dpunkt.verlag und René Schönfeldt danken, der mich sehr professionell bei der Erstellung des Buchs unterstützt hat.

2.7Änderungen in der 2. Auflage

In der zweiten Auflage ist vor allem der Abschnitt 4.3 zu DDD komplett überarbeitet. DDD ist eine wichtige Basis für Microservices, sodass eine bessere Erläuterung sinnvoll ist. Das Beispiel in Kapitel 14 ist komplett überarbeitet, da sich die Technologien weiterentwickeln und mittlerweile neben dem Netflix-Stack auch Alternativen verfügbar sind, die nun in Kapitel 14, aber auch im Rest des Buchs Erwähnung finden.

2.8Links & Literatur

[1]Eberhard Wolff: Continuous Delivery: Der pragmatische Einstieg, dpunkt.verlag, 2. Auflage, 2016, ISBN 978-3-86490-371-7

3Microservice-Szenarien

Dieses Kapitel zeigt einige Szenarien, in denen die Nutzung von Microservices sinnvoll ist. Abschnitt 3.1 betrachtet die Modernisierung einer Legacy-Webanwendung. Dieses Szenario ist der häufigste Einsatzkontext von Microservices. Ein völlig anderes Szenario stellt Abschnitt 3.2 vor. Dort geht es um die Entwicklung eines Signalsystems, das als verteiltes System mit Microservice umgesetzt wird. Abschnitt 3.3 zieht ein Fazit aus den Szenarien und lädt zu einer eigenen Bewertung ein.

3.1Eine E-Commerce-Legacy-Anwendung modernisieren

Szenario

Die Raffzahn Online Commerce GmbH betreibt einen E-Commerce-Shop, von dem der Umsatz des Unternehmens wesentlich abhängt. Es ist eine Webanwendung, die sehr viele unterschiedliche Funktionalitäten anbietet. Dazu zählen die Benutzerregistrierung und -verwaltung, Produktsuche, Überblick über die Bestellungen und der Bestellprozess – das zentrale Feature einer E-Commerce-Anwendung.

Diese Anwendung ist ein Deployment-Monolith: Sie kann nur als Ganzes deployt werden. Bei einer Änderung eines Features muss die gesamte Anwendung neu ausgeliefert werden. Der E-Commerce-Shop arbeitet mit anderen Systemen zusammen – beispielsweise der Buchhaltung und der Lagerhaltung.

Gründe für Microservices

Der Deployment-Monolith war zwar als wohlstrukturierte Anwendung gestartet, aber über die Jahre haben sich mehr und mehr Abhängigkeiten zwischen den Modulen eingeschlichen. Aus diesem Grund ist die Anwendung mittlerweile kaum noch wart- und änderbar. Außerdem ist die ursprüngliche Architektur schon lange nicht mehr angemessen für die aktuellen Anforderungen. So wurde beispielsweise die Produktsuche sehr stark verändert, weil die Raffzahn Online Commerce GmbH sich vor allem in diesem Bereich von den Konkurrenten abheben will. Ebenso sind mehr und mehr Möglichkeiten geschaffen worden, wie Kunden Probleme ohne Kundenservice selber lösen können. Dadurch konnte die Firma ihre Kosten erheblich reduzieren. Dementsprechend sind diese beiden Module mittlerweile sehr groß, intern sehr komplex aufgebaut und haben auch viele Abhängigkeiten zu anderen Modulen, die ursprünglich nicht eingeplant waren.

Langsame Continuous Delivery Pipeline

Raffzahn setzt auf Continuous Delivery und hat eine Continuous-Delivery-Pipeline etabliert. Die Pipeline ist kompliziert und hat eine lange Durchlaufzeit, weil der komplette Deployment-Monolith getestet und in Produktion gebracht werden muss. Einige der Tests dauern Stunden. Schnellere Durchlaufzeiten durch die Pipeline wären sicher wünschenswert.

Parallele Arbeit ist kompliziert.

Es gibt Teams, die an verschiedenen neuen Features arbeiten. Aber die parallele Arbeit ist kompliziert: Die Struktur der Software ist dafür zu schlecht. Die einzelnen Module sind zu schlecht separiert und haben zu viele Abhängigkeiten untereinander. Da alles nur gemeinsam deployt werden kann, muss der gesamte Deployment-Monolith vorher auch getestet werden. Das Deployment und die Testphase sind ein Flaschenhals. Wenn ein Team gerade ein Release in der Deployment-Pipeline hat, aber bei dem Release in diesen Phasen ein Problem auftaucht, müssen alle anderen Teams warten, bis die Änderung erfolgreich deployt worden ist. Und der Durchlauf durch die Deployment-Pipeline muss koordiniert werden. Nur ein Team kann zu einem Zeitpunkt im Test und Deployment sein. So wird geregelt, welches Team welche Änderung wann in Produktion bringen darf.

Flaschenhals bei den Tests

Neben dem Deployment müssen auch die Tests koordiniert werden. Wenn der Deployment-Monolith durch einen Integrationstest läuft, dürfen in dem Test nur die Änderungen eines Teams enthalten sein. Es gab Versuche, mehrere Änderungen auf einmal zu testen. Dann war bei einem Fehler nicht klar, woher das Problem kam, und es gab lange und komplexe Fehleranalysen.

Ein Integrationstest dauert ca. eine Stunde. Pro Arbeitstag sind realistisch sechs Integrationstests möglich, weil Fehler behoben und die Umgebungen wieder hergerichtet werden müssen. Bei zehn Teams kann ein Team im Schnitt ungefähr alle zwei Tage eine Änderung in Produktion bringen. Oft muss ein Team aber Fehleranalyse betreiben – dann verlängert sich die Integration. Daher nutzen einzelne Teams Feature Branches, um sich von der Integration zu entkoppeln: Sie nehmen ihre Änderungen an einem separierten Zweig in der Versionskontrolle vor. Bei der Integration dieser Änderungen in den Hauptzweig kommt es immer wieder zu Problemen: Änderungen werden aus Versehen beim Mergen wieder entfernt oder die Software hat plötzlich Fehler, die durch die getrennte Entwicklung aufgetreten sind. Die Fehler können erst nach einer Integration in langwierigen Prozessen ausgemerzt werden.

Also bremsen sich die Teams durch die Tests gegenseitig aus. Letztendlich arbeiten alle Teams zwar an den eigenen Modulen, aber an derselben Code-Basis, sodass sie sich ausbremsen. Durch die gemeinsame Continuous-Delivery-Pipeline und die dadurch notwendige Koordination sind letztendlich die Teams nicht dazu in der Lage, unabhängig und parallel zu arbeiten.

image

Abb. 3–1Teams bremsen sich durch den Monolithen gegenseitig aus.

Vorgehen

Die Raffzahn Online Commerce GmbH hat sich wegen der vielen Probleme dazu entschieden, kleine Microservices von dem Deployment-Monolithen abzuspalten. Die Microservices implementieren jeweils ein Feature wie beispielsweise die Produktsuche und werden von einem Team verantwortet. Das Team ist von der Anforderungsaufnahme bis zum Betrieb der Anwendung vollständig verantwortlich. Diese Microservices kommunizieren mit dem Monolithen und anderen Microservices über REST. Auch die Benutzeroberfläche ist anhand der fachlichen Anwendungsfälle auf die einzelnen Microservices aufgeteilt. Jeder Microservice liefert die HTML-Seiten für seine Anwendungsfälle aus. Zwischen den HTML-Seiten der Microservices darf es Links geben. Aber es ist nicht erlaubt, auf die Datenbanktabellen der anderen Microservices oder des Deployment-Monolithen zuzugreifen. Ein Datenaustausch zwischen den Services darf ausschließlich über REST oder durch die Verlinkung der HTML-Seiten erfolgen.

Die Microservices können unabhängig voneinander deployt werden. Dadurch ist es möglich, Änderungen in den Microservices ohne Koordinierung mit anderen Microservices oder Teams auszuliefern. Das vereinfacht die parallele Arbeit an Features erheblich und reduziert gleichzeitig den Koordinierungsaufwand.

Der Deployment-Monolith ist durch die Ergänzung um die Microservices wesentlich weniger Änderungen unterworfen. Für viele Features sind gar keine Änderungen am Monolithen mehr notwendig. Daher wird der Deployment-Monolith nun seltener deployt und geändert. Eigentlich war der Plan, den Deployment-Monolithen irgendwann vollständig abzulösen. Aber mittlerweile erscheint es wahrscheinlich, dass der Deployment-Monolith einfach zunehmend seltener deployt wird, weil die meisten Änderungen in den Microservices stattfinden. Dann stört der Deployment-Monolith aber nicht mehr. Eine vollständige Ablösung ist eigentlich überflüssig und erscheint wirtschaftlich nicht mehr sinnvoll.

Herausforderungen

Durch die Umsetzung der Microservices entsteht zunächst zusätzliche Komplexität: Die vielen Microservices benötigen eigene Infrastrukturen. Parallel muss der Monolith weiter unterstützt werden.

Die Microservices umfassen wesentlich mehr Server und stellen daher ganz andere Anforderungen. Das Monitoring und die Verarbeitung der Logdateien müssen damit umgehen, dass die Daten auf verschiedenen Servern anfallen. Also müssen die Informationen zentral konsolidiert werden. Außerdem muss eine wesentlich größere Anzahl Server angeboten werden – und zwar nicht nur in Produktion, sondern auch in den verschiedenen Test-Stages und auch Umgebungen für die einzelnen Teams sind sie notwendig. Das stellt wesentlich höhere Anforderungen an die Infrastruktur-Automatisierung. Es müssen nicht nur zwei unterschiedliche Arten von Infrastrukturen für den Monolithen und die Microservices unterstützt werden, sondern unter dem Strich auch wesentlich mehr Server.

Vollständige Migration ist langwierig.

Die zusätzliche Komplexität durch die beiden unterschiedlichen Software-Arten wird sehr lange vorhanden sein, denn die vollständige Migration weg vom Monolithen ist ein langwieriger Prozess. Wenn der Monolith niemals vollständig abgelöst wird, werden auch die zusätzlichen Infrastrukturkosten bestehen bleiben.

Testen bleibt eine Herausforderung.

Eine weitere Herausforderung ist das Testen: Bisher wurde der gesamte Deployment-Monolith in der Deployment-Pipeline getestet. Diese Tests sind aufwendig und dauern lange, weil sie alle Funktionalitäten im Deployment-Monolithen testen müssen. Wenn jede Änderung an jedem Microservice durch diese Tests geschickt wird, dauert es sehr lange, bis die Änderungen in Produktion sind. Außerdem müssen die Änderungen koordiniert werden, denn jede Änderung sollte einzeln getestet werden, damit gegebenenfalls klar ist, welche Änderung einen Fehler ausgelöst hat. Damit ist dann gegenüber dem Deployment-Monolithen nicht viel gewonnen: Das Deployment wäre zwar unabhängig voneinander möglich, aber die Test-Stages vor dem Deployment müssen immer noch koordiniert und von jeder Änderung einzeln durchlaufen werden.

image

Abb. 3–2Entkoppelte Arbeit durch Microservices

Aktueller Stand der Migration

Abbildung 3–2 zeigt den aktuellen Stand: Die Produktsuche arbeitet auf ihrem eigenen Microservice und vollständig unabhängig vom Deployment-Monolithen. Eine Koordinierung mit den anderen Teams ist kaum noch notwendig. Nur im letzten Schritt des Deployments müssen der Deployment-Monolith und die Microservices gemeinsam getestet werden. Diesen Schritt muss jede Änderung des Monolithen und aller Microservices durchlaufen. Dadurch ist ein Flaschenhals entstanden. Das Team »Benutzer« arbeitet gemeinsam unter anderem mit dem Team »Bestellprozess« am Deployment-Monolithen. Diese Teams müssen sich trotz Microservices immer noch eng abstimmen. Daher hat das Team »Bestellprozess« einen eigenen Microservice umgesetzt, der einen Teil des Bestellprozesses umfasst. Änderungen in diesem Teil des Systems sind im Vergleich zum Deployment-Monolithen nicht nur wegen der jüngeren Code-Basis schneller umgesetzt, sondern auch weil die Koordination mit den anderen Teams entfällt.

Aufstellung der Teams

Voraussetzung für die unabhängige Arbeit an Features ist die Aufstellung der Teams nach Fachlichkeiten wie Produktsuche, Benutzer oder Bestellprozess. Wenn stattdessen die Teams nach technischen Merkmalen wie UI, Middle Tier oder Datenbank aufgestellt sind, muss für jedes Feature jedes Team beteiligt werden. Schließlich wird ein Feature meistens Änderungen in UI, Middle Tier und Datenbank umfassen. Um Koordination zwischen den Teams zu minimieren, ist eine Aufstellung der Teams nach Fachlichkeiten auf jeden Fall sinnvoll. Microservices unterstützen die Unabhängigkeit durch eine technische Unabhängigkeit der einzelnen Services. Deswegen müssen Teams sich auch viel weniger bezüglich Basistechnologien und grundlegenden technischen Entwürfen koordinieren.

Die Tests müssen ebenfalls modularisiert werden. Jeder Test sollte einem einzigen Microservice zugeschlagen werden. Dann reicht es, wenn der Test bei Änderungen an diesem Microservice ausgeführt wird. Außerdem kann es sein, dass der Test dann als Unit-Test umgesetzt werden kann statt als Integrationstest. So wird die Testphase, in der alle Microservices und der Monolith gemeinsam getestet werden, zunehmend kürzer. Das verringert das Problem der Koordination für die letzte Testphase.

Die Migration hin zu einer Microservices-Lösung hat einige Performance-Probleme erzeugt und auch Probleme bei Netzwerkausfällen. Diese Schwierigkeiten konnten allerdings mit der Zeit gelöst werden.

Nutzen

Dank der neuen Architektur können Änderungen wesentlich schneller deployt werden. Eine Änderung kann von einem Team innerhalb von 30 Minuten in Produktion gebracht werden. Der Deployment-Monolith hingegen wird wegen der teilweise noch nicht automatisierten Tests nur wöchentlich deployt.

Neben der höheren Geschwindigkeit sind die Deployments der Microservices auch sonst wesentlich angenehmer: Es ist viel weniger Koordinierung notwendig. Fehler können schneller gefunden und behoben werden, weil die Entwickler noch sehr genau wissen, woran sie gearbeitet haben – schließlich ist das nur 30 Minuten her.

Letztendlich wurde das Ziel erreicht: Die Entwickler können viel mehr Änderungen an dem E-Commerce-Shop vornehmen. Das ist möglich, weil die Teams ihre Arbeit wesentlich weniger koordinieren müssen und weil die Deployments der Services unabhängig voneinander erfolgen können.

Die Möglichkeit, unterschiedliche Technologien zu nutzen, haben die Teams sparsam genutzt: Der bisher verwendete Technologie-Stack war ausreichend. Zusätzliche Komplexität durch den Einsatz von unterschiedlichen Technologien wollten die Teams vermeiden. Allerdings wurde für die Produktsuche die lange überfällige Suchmaschine eingeführt. Diese Änderung konnte von dem Team, das für die Produktsuche verantwortlich ist, alleine durchgeführt werden. Zuvor war die Einführung dieser neuen Technologie lange Zeit unterbunden worden, weil das Risiko als zu groß eingeschätzt wurde. Und einige Teams haben mittlerweile neue Versionen der Bibliotheken aus dem Technologie-Stack in Produktion, weil sie auf die Bug Fixes angewiesen waren. Dazu war keine Koordination über die Teams notwendig.

Bewertung

Das Ablösen eines Monolithen durch das Einführen von Microservices ist schon fast ein Klassiker für die Einführung von Microservices. Monolithen weiterzuentwickeln und mit neuen Features zu versehen, ist aufwendig. Die Komplexität und damit die Probleme des Monolithen nehmen über die Zeit zu. Eine vollständige Ablösung durch eine andere Software ist schwierig, weil dann die Software komplett ersetzt werden muss – und das ist risikoreich.

Schnelle und unabhängige Entwicklung neuer Features

Gerade bei Unternehmen wie der Raffzahn Online Commerce GmbH sind die schnelle Entwicklung neuer Features und die parallele Arbeit an mehreren Features überlebenswichtig. Nur so können Kunden gewonnen und davon abgehalten werden, zu anderen Anbietern zu wechseln. Das Versprechen, mehr Features schneller zu entwickeln, machen Microservices für viele Einsatzkontexte sehr attraktiv.

Einfluss auf die Organisation

Dieses Beispiel verdeutlicht auch den Einfluss von Microservices auf die Organisation. Die Teams arbeiten jeweils auf eigenen Microservices. Weil die Microservices unabhängig voneinander entwickelt und deployt werden können, ist die Arbeit der Teams voneinander entkoppelt. Dazu darf aber ein Microservice nicht von mehreren Teams parallel weiterentwickelt werden. Zu der Microservices-Architektur gehört eine Organisation der Teams entsprechend den Microservices: Jedes Team ist für einen oder mehrere Microservices zuständig, die eine isolierte Funktionalität umsetzen. Diese Beziehung zwischen Organisation und Architektur ist gerade bei Microservices sehr wichtig. Die Teams kümmern sich um alle Belange des Microservice von der Anforderungsaufnahme bis hin zur Betriebsüberwachung. Selbstverständlich können gerade für den Betrieb gemeinsame Infrastrukturdienste für Logging oder Monitoring genutzt werden.

Und schließlich: Wenn das Ziel ein einfaches und schnelles Deployment in Produktion ist, reicht die Umstellung der Architektur auf Microservices nicht aus. Die gesamte Continuous-Delivery-Pipeline muss auf Hindernisse untersucht und diese müssen ausgeräumt werden. Das zeigen im Beispiel die Tests: Ein gemeinsames Testen sollte auf das notwendige Minimum beschränkt sein. Jede Änderung muss einzeln einen Integrationstest mit den anderen Microservices durchlaufen, aber der darf nicht besonders lange dauern.