Microservices

Konzeption und Design

Sam Newman

Übersetzung aus dem Amerikanischen von Knut Lorenzen

Impressum

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 978-3-95845-083-7

1. Auflage 2015

www.mitp.de

E-Mail: mitp-verlag@sigloch.de

Telefon: +49 7953 / 7189 - 079

Telefax: +49 7953 / 7189 - 082

© 2015 mitp Verlags GmbH & Co. KG

Dieses Werk, einschließlich aller seiner Teile, ist urheberrechtlich geschützt. Jede Verwertung außerhalb der engen Grenzen des Urheberrechtsgesetzes ist ohne Zustimmung des Verlages unzulässig und strafbar. Dies gilt insbesondere für Vervielfältigungen, Übersetzungen, Mikroverfilmungen und die Einspeicherung und Verarbeitung in elektronischen Systemen.

Die Wiedergabe von Gebrauchsnamen, Handelsnamen, Warenbezeichnungen usw. in diesem Werk berechtigt auch ohne besondere Kennzeichnung nicht zu der Annahme, dass solche Namen im Sinne der Warenzeichen- und Markenschutz-Gesetzgebung als frei zu betrachten wären und daher von jedermann benutzt werden dürften.

Authorized German translation of the English edition of Building Microservices ISBN 9781491950357 © 2015 Sam Newman. This translation is published and sold by permission of O’Reilly Media, Inc., which owns or controls all rights to publish and sell the same.

Lektorat: Sabine Schulz

Sprachkorrektorat: Maren Feilen

Coverbild: © Irochka, fotolia.de

electronic publication: III-satz, Husby, www.drei-satz.de

Dieses Ebook verwendet das ePub-Format und ist optimiert für die Nutzung mit dem iBooks-reader auf dem iPad von Apple. Bei der Verwendung anderer Reader kann es zu Darstellungsproblemen kommen.

Der Verlag räumt Ihnen mit dem Kauf des ebooks das Recht ein, die Inhalte im Rahmen des geltenden Urheberrechts zu nutzen. Dieses Werk, einschließlich aller seiner Teile, ist urheberrechtlich geschützt. Jede Verwertung außerhalb der engen Grenzen des Urheherrechtsgesetzes ist ohne Zustimmung des Verlages unzulässig und strafbar. Dies gilt insbesondere für Vervielfältigungen, Übersetzungen, Mikroverfilmungen und Einspeicherung und Verarbeitung in elektronischen Systemen.

Der Verlag schützt seine ebooks vor Missbrauch des Urheberrechts durch ein digitales Rechtemanagement. Bei Kauf im Webshop des Verlages werden die ebooks mit einem nicht sichtbaren digitalen Wasserzeichen individuell pro Nutzer signiert.

Bei Kauf in anderen ebook-Webshops erfolgt die Signatur durch die Shopbetreiber. Angaben zu diesem DRM finden Sie auf den Seiten der jeweiligen Anbieter.

Kapitel 12: Auf den Punkt gebracht

In den vorhergehenden Kapiteln wurden viele Themen erörtert: Die Grundlagen einer Microservice-Architektur, die Definition der Schnittstellen, Technologien zur Integration und Aspekte der Sicherheit und des Monitorings. Es blieb sogar Raum, um darüber nachzudenken, wie sich die Rolle des Systemarchitekten in das Gesamtbild einfügt. Das ist schon eine ganze Menge, denn auch wenn die Microservices selbst eher klein sind, haben sie doch großen Einfluss auf die Systemarchitektur. Im Folgenden möchte ich nun die wichtigsten der im Buch behandelten Themen noch einmal zusammenfassen.

12.1  Prinzipien​

In Kapitel 2 wurde die Bedeutung der grundlegenden Prinzipien einer Microservice-Architektur erörtert. Sie geben vor, auf welche Art und Weise die verschiedenen Aufgaben erledigt werden sollten und begründen das auch. Sie stecken einen Rahmen für die bei der Entwicklung eines Systems zu treffenden Entscheidungen. Sie sollten unter allen Umständen Ihre eigenen Prinzipien festlegen, dennoch habe ich Ihnen die meiner Ansicht nach wichtigsten Grundprinzipien einer Microservice-Architektur, die bei der Entwicklung kleiner, voneinander unabhängiger und miteinander kollaborierender Services als Leitfaden dienen, einmal in Abbildung 12.1 zusammengestellt. Hier findet sich eigentlich nichts Neues, denn die aufgeführten Prinzipien wurden bereits – zum Teil mehrfach – erörtert, dennoch lohnt es sich, sie einmal auf den Punkt zu bringen.

Sie können diese Prinzipien pauschal übernehmen oder sie an die Gegebenheiten in Ihrem Unternehmen anpassen. Beachten Sie insbesondere den positiven Effekt der Kombination dieser Prinzipien: Das Ganze ist mehr als die Summe seiner Teile. Wenn Sie sich dazu entschließen, eins dieser Grundprinzipien außer Acht zu lassen, sollten Sie sich klar machen, was Ihnen dadurch entgeht.

Ich werde mich im Folgenden bemühen, zu jedem der genannten Prinzipien zugehörige Praktiken zu benennen, die im Buch erörtert wurden. Aber wie heißt es doch so schön: Alle Wege führen nach Rom! Sie können also auch Ihre eigenen Praktiken zur Umsetzung dieser Prinzipien entwickeln – zumindest finden Sie hier jedoch einen Ausgangspunkt.

Abb. 12.1: Prinzipien einer Microservice-Architektur

12.1.1  Geschäftsvorgänge modellieren

Die Erfahrung lehrt, dass an Geschäftsvorgängen​ orientierte Schnittstellen stabiler sind als an technischen Konzepten ausgerichtete. Wenn wir in unserem System Geschäftsbereiche nachbilden, versuchen wir damit nicht nur stabilere Schnittstellen zu erzielen, sondern auch zu gewährleisten, dass sich das System leichter an veränderte Geschäftsvorgänge anpassen lässt. Verwenden Sie begrenzte Kontexte, um die Schnittstellen zu verschiedenen Geschäftsbereichen festzulegen.

12.1.2  Automatisierung kultivieren

Microservices bringen nicht zuletzt aufgrund der großen Anzahl veränderlicher Systembestandteile einige Komplexität mit sich. Das Bestreben, die Automatisierung​ zu kultivieren, ist dazu geeignet, dem zu begegnen, und es kann durchaus sinnvoll sein, von vornherein Anstrengungen zu unternehmen, Microservices zu unterstützen. Automatisiertes Testen ist von entscheidender Bedeutung, denn das Funktionieren der Services zu gewährleisten ist komplizierter als bei monolithischen Systemen. Ein Kommandozeilenaufruf für das einheitliche Deployment ist dabei sehr nützlich und ermöglicht es, im Rahmen des Continuous Delivery nach dem Einchecken schnell Rückmeldung zur Qualität des Produktivsystems zu erhalten.

Ziehen Sie in Betracht, Umgebungsdefinitionen zu verwenden, um die Unterschiede zwischen verschiedenen Umgebungen zu dokumentieren, ohne dabei die einheitliche Deployment-Methode aufzugeben. Mittels maßgeschneiderter Images können Sie das Deployment beschleunigen, und die Einrichtung vollständig automatisierter unveränderlicher Server erleichtert es, die Funktionsweise Ihres Systems zu verstehen.

12.1.3  Implementierungsdetails verbergen

Um einen Service unabhängig von anderen Services fortentwickeln zu können, ist es erforderlich, Implementierungsdetails​ zu verbergen. Hier ist die Verwendung begrenzter Kontexte hilfreich, weil wir uns darauf konzentrieren können, welche Modelle gemeinsam genutzt und welche verborgen werden sollen. Außerdem sollten Services ihre Datenbank verbergen, um eine bei herkömmlichen serviceorientierten Architekturen so häufig auftretende Kopplung zu vermeiden, und stattdessen Datenpumpen oder Ereignis-Datenpumpen verwenden, um die zur Berichterstellung erforderlichen Daten verschiedener Services zusammenzuführen.

Verwenden Sie nach Möglichkeit technologieunabhängige APIs, um bei der Auswahl der einzusetzenden Technologie keinen Einschränkungen zu unterliegen. Ziehen Sie in Betracht, REST zu verwenden, das die Trennung interner und externer Implementierungsdetails formalisiert. Diese Konzepte können aber auch bei der Nutzung von RPC (Aufruf entfernter Prozeduren) Anwendung finden.

12.1.4  Dezentralisierung​

Zur Maximierung der durch Microservices ermöglichten Autonomie ist es erforderlich, laufend nach Möglichkeiten zu suchen, Entscheidungen und Zuständigkeiten an diejenigen Teams zu delegieren, die für den Service selbst verantwortlich sind. Dazu gehört auch, für möglichst viele Dinge Selbstbedienungsverfahren einzurichten, damit die Entwickler ihre Software nach Bedarf deployen können, was die Entwicklung und das Testen sehr erleichtert. Außerdem entfällt so die Notwendigkeit, dass verschiedene Teams diese Aufgabe erledigen müssen.

Teams sind für ihre Services verantwortlich – das ist hier ganz entscheidend. Im Idealfall ist das Entwicklerteam nicht nur für die vorgenommenen Modifikationen verantwortlich, sondern entscheidet auch selbst, wann diese veröffentlicht werden. Interner Open-Source-Code ermöglicht, dass die Entwickler Änderungen an Services vornehmen können, für die andere Teams verantwortlich sind, bedenken Sie aber, dass mit der Implementierung viel Arbeit verbunden sein kann. Stimmen Sie die Teams auf Ihre Organisationstruktur ab, damit Conways Gesetz in Ihrem Sinne arbeitet und die Teams zu Experten auf dem Gebiet der Geschäftsprozesse werden, für die sie Services entwickeln. Wenn eine bereichsübergreifende Führung erforderlich ist, können Sie ein Modell der gemeinschaftlichen Governance in Betracht ziehen, bei dem sich Mitglieder verschiedener Teams die Verantwortung für die Weiterentwicklung des technischen Leitbildes des Systems teilen.

Dasselbe Prinzip ist auch auf Architekturen anwendbar. Verzichten Sie lieber auf Ansätze wie Enterprise Service Bus oder Systeme zur Orchestrierung, die oft zu einer Zentralisierung der Geschäftslogik und trivialen Services führen. Geben Sie statt einer Orchestrierung lieber einer Choreografie und nicht zu schlauer Middleware mit der Programmlogik in den Endpunkten den Vorzug, um zusammengehörende Programmlogik und Daten innerhalb eines Services zu belassen und dadurch zur Geschlossenheit beizutragen.

12.1.5  Unabhängiges Deployment​​

Wir sollten stets darum bemüht sein, dass das Deployment unserer Services voneinander unabhängig durchgeführt werden kann und dies auch praktizieren. Selbst wenn zu Ausfällen führende Modifikationen anstehen, kann man versuchen, mehrere Versionen eines Endpunktes gleichzeitig zu betreiben, um den Consumern Zeit für den Wechsel zu der neuen Version zu geben. Diese Vorgehensweise gestattet die schnellstmögliche Veröffentlichung neuer Features und erhöht gleichzeitig die Eigenständigkeit des für den Service verantwortlichen Teams, das sich nicht mehr bei jedem Deployment um die Orchestrierung kümmern muss. Wenn Sie RPC-Verfahren einsetzen, sollten Sie die Erzeugung eng gekoppelter Client/Server-Platzhalter vermeiden, wie sie bei Java RMI Verwendung finden.

Durch ein Ein-Service-pro-Host-Modell lassen sich Nebenwirkungen vermeiden, die durch das Deployment eines Services bei anderen Services verursacht werden können. Ziehen Sie ein Blue/Green-Deployment und eine Canary-Veröffentlichung in Betracht, um Deployment und Veröffentlichung voneinander abzugrenzen und die mit der Veröffentlichung verbundenen Risiken zu reduzieren. Verwenden Sie Consumer-Driven Contracts (CDCs), um Modifikationen aufzuspüren, die zu Ausfällen führen würden, damit sie gar nicht erst stattfinden können.

Halten Sie sich stets vor Augen, dass es nicht die Ausnahme, sondern die Regel sein sollte, Änderungen an einzelnen Services des Produktivsystems vornehmen und veröffentlichen zu können, ohne gleichzeitig irgendwelche anderen Services deployen zu müssen. Die Consumer sollten entscheiden, wann sie Aktualisierungen durchführen – und Sie müssen diesem Anliegen nachkommen.

12.1.6  Ausfälle eingrenzen​

Eine Microservice-Architektur kann belastbarer als ein monolithisches System sein, allerdings nur dann, wenn mögliche Ausfälle von Teilen des Systems eingeplant werden. Wenn wir der Tatsache, dass nachgeschaltete Services ausfallen können und werden, nicht Rechnung tragen, kann es zu katastrophalen Kettenreaktionen kommen, die in der Konsequenz zu einem sehr viel anfälligeren System führen.

Wenn Sie Funktionen über das Netzwerk aufrufen, dürfen Sie entfernte Aufrufe keinesfalls als lokale Aufrufe betrachten, weil dadurch verschiedene Fehlerzustände verborgen bleiben. Sie sollten sich daher vergewissern, dass die eingesetzten Client-Bibliotheken die Abstrahierung entfernter Aufrufe nicht übertreiben.

Folgen wir den Maximen der Antifragilität und gehen davon aus, dass jederzeit und überall mit einem Ausfall zu rechnen ist, sind wir auf dem rechten Weg. Vergewissern Sie sich, dass Ihre Timeouts korrekt eingestellt sind. Finden Sie heraus, ob der Einsatz von Bulkheads und Circuit Breakers sinnvoll wäre, um die negativen Folgen des Ausfalls einer Komponente zu begrenzen. Machen Sie sich klar, welche Auswirkungen es für Consumer hat, wenn nur ein Teil des Systems ein Fehlverhalten zeigt. Die Folgen zu kennen, wenn aufgrund einer Netzwerkstörung Teile des Systems nicht miteinander kommunizieren können, und beurteilen zu können, ob es in einer bestimmten Situation besser ist, die Verfügbarkeit oder die Konsistenz aufzugeben, sind genau das Richtige.

12.1.7  Umfassendes Monitoring​

Das Verhalten eines einzelnen Services oder den Betriebszustand einer einzelnen Maschine zu überwachen, reicht nicht aus, um zu beurteilen, ob das Gesamtsystem funktionsfähig ist. Wir benötigen stattdessen eine umfassendere Übersicht über das Geschehen. Verwenden Sie semantisches Monitoring, um die korrekte Arbeitsweise des Systems zu überprüfen, indem Sie Pseudo-Ereignisse auslösen, um das Verhalten echter Anwender zu simulieren. Fassen Sie Protokolle und Statistiken zusammen, damit Sie auftretenden Störungen auf den Grund gehen können. Und wenn es darum geht, hartnäckige Probleme nachzuvollziehen oder einfach nur die Funktionsweise des Produktivsystems zu beobachten, können Sie Korrelations-IDs verwenden, um Aufrufketten innerhalb des Systems nachzuverfolgen.

12.2  Wann sollte man auf Microservices verzichten?​

Diese Frage wird mir sehr oft gestellt. Mein erster Rat ist folgender: Wenn Sie die Prozesse eines Geschäftsbereiches nicht besonders gut verstehen, wird es Ihnen schwerfallen, die richtigen begrenzten Kontexte für Ihre Services zu finden. Wie bereits erwähnt, kann eine ungeeignete Aufspaltung viele Modifikationen in Bezug auf die Zusammenarbeit verschiedener Services erforderlich machen – eine ziemlich aufwendige Arbeit. Wenn Sie die Geschäftsprozesse eines monolithischen Systems nicht ganz durchschauen, sollten Sie zunächst etwas Zeit darin investieren, die Arbeitsweise des Systems besser kennenzulernen, um dann eine klare Modularisierung vorzunehmen, die als Grundlage für eine Aufspaltung in Services dienen kann.

Auch ein »Grüne-Wiese«-Ansatz, also ein vollständige Neuentwicklung, kann eine Herausforderung darstellen. Das liegt nicht nur daran, dass der Geschäftsbereich vermutlich neu ist, sondern dass es viel einfacher ist, etwas Vorhandenes aufzuspalten als etwas, das noch gar nicht existiert! Ziehen Sie in Betracht, zunächst eine monolithische Anwendung zu entwickeln und diese aufzuspalten, wenn sie sich stabilisiert hat.

Viele der Schwierigkeiten, mit denen Sie sich bei der Entwicklung von Microservices konfrontiert sehen, werden durch eine Skalierung verschärft. Wenn Sie die meisten Dinge von Hand erledigen, mag das mit ein oder zwei Services noch funktionieren. Aber mit fünf? Oder zehn? An der herkömmlichen Monitoring-Praxis festzuhalten, bei der nur CPU- und Speicherauslastung eine Rolle spielen, mag mit einigen wenigen Services ebenfalls noch machbar sein, doch je mehr Services miteinander verknüpft sind, desto mühsamer wird die Angelegenheit. Irgendwann überschreiten Sie beim Hinzufügen von Services eine Schmerzgrenze und ich hoffe, die Ratschläge in diesem Buch können Ihnen dabei helfen, einige der auftretenden Probleme frühzeitig zu erkennen und besser mit ihnen zurechtzukommen. Ich habe davon berichtet, wie viel Zeit es REA und Gilt gekostet hat, die erforderlichen Werkzeuge zusammenzutragen und Praktiken zu entwickeln, bis sie in der Lage waren, Microservices in größerem Stil einzusetzen. Meiner Ansicht nach untermauern diese Beispiele, wie wichtig es ist, langsam anzufangen und zunächst den Willen und die Fähigkeit Ihres Unternehmens für Modifikationen auszuloten. Dieses Wissen wird Ihnen bei der sachgerechten Einführung von Microservices helfen.

12.3  Schlusswort

Microservice-Architekturen bieten Ihnen viele Optionen und Sie müssen zusätzliche Entscheidungen treffen. Im Microservice-Umfeld sind erheblich mehr Entscheidungen zu fällen als bei einfachen monolithischen Systemen – und ich kann Ihnen garantieren, dass Sie auch Fehlentscheidungen treffen werden. Wenn wir aber schon wissen, dass es Fehlentscheidungen geben wird, was können wir dann dagegen unternehmen? Nun, ich würde empfehlen, nach Möglichkeiten zu suchen, nur Entscheidungen von lediglich geringer Tragweite treffen zu müssen. Auf diese Weise ist nur ein kleiner Teil Ihres Systems betroffen, wenn Ihnen ein Fehler unterläuft. Freunden Sie sich mit dem Konzept einer sich ständig fortentwickelnden Architektur an, bei dem sie fortlaufend an Ihrem System herumfeilen und Änderungen vornehmen, während Sie Erfahrungen sammeln. Es geht dabei nicht darum, in großem Stil neuen Code zu schreiben, sondern um viele kleine Anpassungen am System, damit es flexibel bleibt.

Ich habe von meinen Erfahrungen berichtet und Sie sind nun hoffentlich so gut informiert, dass Sie entscheiden können, ob Microservices für Ihre Zwecke geeignet sind. Wenn dem so ist: Der Weg ist das Ziel. Gehen Sie schrittweise vor. Spalten Sie Ihr System nach und nach auf und sammeln Sie dabei Erfahrung. Und gewöhnen Sie sich an den Gedanken, dass die Disziplin zur kontinuierlichen Fortentwicklung Ihrer Systeme in vielerlei Hinsicht wichtiger ist als alle anderen Dinge, über die ich in diesem Buch geschrieben habe. Ein Wandel ist unausweichlich. Heißen Sie ihn willkommen.