# Microservices

Microservices sind ein Architekturmuster der Informationstechnik, bei dem komplexe Anwendungssoftware aus unabhängigen Prozessen generiert wird, die untereinander mit sprachunabhängigen Programmierschnittstellen kommunizieren. Die Dienste sind weitgehend entkoppelt und erledigen eine kleine Aufgabe. So ermöglichen sie einen modularen Aufbau von Anwendungssoftware.

## Philosophie und Details

Der Gedanke hinter Microservices entspricht weitgehend dem der Unix-Philosophie („Do One Thing and Do It Well“, frei übersetzt: „Erledige nur eine Aufgabe und erledige sie gut“). Die Dienste sollten üblicherweise die folgenden Eigenschaften haben:
* Die Services können einfach ersetzt werden.
** Der Umfang eines Microservices sollte für jedes Teammitglied überschaubar sein.
** Ein Microservice sollte vom zuständigen Team (üblicherweise 5 bis 7 Entwickler) mit vertretbarem Zeitaufwand (z. B. innerhalb eines Monats) neu erstellt und ersetzt werden können.
* Ein Microservice sollte einen Bounded Context im Sinne von Domain-driven Design implementieren.
** Die Dienste haben eine einzige Geschäftsfunktion. Sie können beispielsweise einen Bestellvorgang, die Registrierung oder die Rechnungserstellung umfassen, jedoch nicht mehrere dieser Dinge.
* Der Nutzen für den Benutzer steht im Mittelpunkt.
** Die Kernfunktionalität sollte frühzeitig ausgeliefert werden, um einen möglichst frühen Nutzen bereitzustellen.
** Schnittstellen sollten, z. B. über Humane Registries, selbstdokumentierend sein. Beispielsweise Swagger für JSON-basierte REST-Services.
** Nach der Bereitstellung einer neuen Version des Services muss die alte Version des Endpunktes für eine bestimmte Zeit weiter bereitgestellt werden. → Hauptartikel: REST-Versionierung
* Ein Microservice wird nur von einem Team entwickelt. Die Architektur liegt über den Microservices und ist auf Grund des Gesetzes von Conway durch die Teamaufteilung sichtbar. Alternativ dazu kann ein Team für mehrere fachlich zusammenhängende Microservices verantwortlich sein.
** Kommunikationsoverhead und Interessenskonflikte zwischen Teams werden auf der Ebene der Architektur behandelt.
* Die Schnittstellen verstecken Implementierungsdetails.
** Es werden dabei bevorzugt Standardverfahren mit geringem Overhead, wie REST, eingesetzt.
** Es sollte nicht ersichtlich sein, mit welcher Architektur ein Microservice selbst implementiert wurde.
** Datenbanken werden nicht von mehreren Services verwendet, sondern immer nur von einem einzigen Service. Dies betrifft auch Zugriffe über Views und Stored Procedures.
* Microservices werden gegenüber anderen Services isoliert.
** Jeder Microservice kann eine andere Programmiersprache, Datenbank oder einen ganz anderen Technologie-Stack nutzen.
** Microservices sollten Abhängigkeiten untereinander vermeiden und wenn dann nur asynchrone Abhängigkeiten haben.
** Jeder Microservice sollte unabhängig von anderen Microservices in Produktion gebracht werden können.
** Objekte, welche in mehreren Bounded Contexts vorkommen, werden in jedem Service getrennt implementiert. Beispielsweise wird derselbe Kunde in einem Authentifizierungssystem, einem Bestellsystem, einem Logistiksystem und einem Rechnungssystem jeweils durch unterschiedliche Objekte repräsentiert, da an die Objekte unterschiedliche Anforderungen gestellt werden.
** Microservices werden in getrennten OS-Containern, virtuellen Maschinen oder Servern ausgeliefert. Dies sichert den Service gegenüber einer Überlastung des Host-Systems durch einen anderen Service.
* Wie alle Services müssen auch Microservices sicher sein:
** Microservices sollten dezentralisiert und horizontal skalierbar sein. Funktionale Architekturen mit Zustandsfreiheit werden bevorzugt. Dies betrifft etwa Caches (z. B. zum Speichern von Benutzer-Sessions), welche als eigener Service, etwa in Form einer In-Memory Key-Value-Datenbank, ausgeführt werden müssen.
** Microservices isolieren Fehlerereignisse und -zustände von anderen Services.
** Logging, Monitoring und Operations-Datenbanken ermöglichen die Beobachtbarkeit.
** Authentifizierung, Autorisierung und Kryptographie sichern die Daten vor ungewünschtem Zugriff.
Die Größe eines Microservices wird hierbei dadurch nach unten begrenzt, dass die Netzwerkkommunikation zwischen Microservices ressourcenintensiv ausfallen kann und für jeden Microservice ein eigenes Deployment vorgesehen werden muss.

## Typische Bestandteile einer Microservice-Architektur

Microservices benötigen sehr viel Infrastruktur, welche durch jeweils eigenständige Services implementiert wird.
Für die Lastverteilung externer HTTP-Anfragen von Clienten kommen Load-Balancer zum Einsatz. Statische Inhalte werden mittels eines Content Delivery Network ausgeliefert.
Die für die Geschäftsanforderungen zuständigen Services werden durch eine Reihe von Plattform- oder Infrastruktur-Services unterstützt. Diese übernehmen zentrale Aufgaben wie das Anwendungs- und Service-Monitoring, Logging-Webservices, Operations-Datenbanken, Konfigurationsmanagement, Verschlüsselung, Autorisierung und Authentifizierung, sowie Autoscaling, Softwareverteilung, A/B-Testing und Fault-Injection-Testing (FIT). Zudem gibt es zentrale Routingdienste, welche sich um die Zuordnung von URLs zu Instanzen mit den jeweiligen Diensten kümmern.
Hierzu kommen noch Dienste für die Datenpersistierung, insbesondere Caching, relationale Datenbanken und NoSQL-Datenbanken, sowie BLOB-Speicher für beliebige Dateien.

## Abgrenzung zu SOA

Sowohl SOA (Serviceorientierte Architektur) als auch Microservices nutzen Dienste als Architektur-Elemente.
SOA nutzt Dienste, um verschiedene Anwendungen zu integrieren. Die Kombination der Dienste erfolgt durch Orchestrierung oder Choreografie, und Portale können eine gemeinsame Benutzerschnittstelle (UI) für alle Dienste bieten.
Microservices strukturieren eine Anwendung durch Dienste. Jeder Microservice kann eine Benutzerschnittstelle enthalten und Geschäftsprozesse implementieren, wie sie bei SOA in der Orchestrierung zu finden sind.

## Vorteile

* Weil Microservices unabhängig voneinander verteilt und entwickelt werden können, können Teams unabhängiger voneinander arbeiten. Das ermöglicht die Skalierung agiler Entwicklungs-Prozesse, ohne viel Kommunikations- und Koordinationsaufwand zu erzeugen.
* Microservices sind idealerweise klein. Dadurch bleiben sie übersichtlich und leicht weiterentwickelbar. Bei Bedarf können sie durch eine Neuimplementierung ersetzt werden.
* Oft schleichen sich bei Systemen ungewollte Abhängigkeiten ein. Die Abhängigkeiten zwischen Microservices müssen über die API eingeführt werden. Das ist aufwändig und passiert nicht aus Versehen.
* Microservices können unabhängig voneinander skaliert werden.
* Microservice-Systeme können gegen den Ausfall anderer Services abgesichert werden, so dass das Gesamtsystem robust ist.
* Wenn Schlüsseldienste identifiziert wurden, können im Falle einer Überlastung unkritische Services reduziert oder abgeschaltet werden, um Ressourcen für kritische Services frei zu machen.

## Nachteile

Microservices werden wegen einiger Merkmale kritisiert:
* Die Abhängigkeiten zwischen den Microservices sind bei einer Microservicearchitektur nicht offensichtlich. Es ist oftmals unklar, welche Microservices welche anderen Microservices in welcher Version benötigen.
* Die verteilte Architektur erzeugt zusätzliche Komplexität, vor allem Netzwerk-Latenzen, Lastverteilung oder Fehlertoleranz (siehe dazu auch: Fallacies of Distributed Computing).
* Da es mehr Systeme gibt die ausfallen können als bei monolithischen Services, steigt auch die Wahrscheinlichkeit, dass mindestens eine Komponente ausfällt. Wenn die Microservices wie üblich untereinander synchrone Abhängigkeiten haben, wirkt sich der Ausfall eines Microservices unmittelbar auf das Gesamtsystem aus.
* Die Vielzahl an Services macht die Softwareverteilung und das Testen komplexer.
* Der Aufwand für die Migration bestehender Systeme ist beträchtlich und bedeutet in der Regel auch eine Anpassung der Kommunikationskultur in den beteiligten Organisationen.
* Das Logging und Monitoring wird komplexer, da mehrere Systeme involviert sind, welche ggf. unterschiedliche Logging- und Monitoringtechnologien einsetzen. Es sollten daher, zusätzlich zu dezentralen Logging- und Monitoringlösungen, zentrale Logging-, Monitoring- und OpsDB-Dienste eingesetzt werden.
* Da es sich um ein potenziell weltweit verteiltes System handelt, müssen nicht nur unterschiedliche Zeitzonen der Client-Anwendungen, sondern auch unterschiedliche Zeitzonen der Hosts berücksichtigt werden. Eine Zeitsynchronisierung zwischen den Hosts (z. B. mittels NTP oder noch besser PTP) und die Verwendung passender Zeit-Bibliotheken (z. B. Joda Time oder Noda Time) wird damit zwingend notwendig.
* Da es sich bei Microservices um eine verteilte Architektur handelt, muss aufgrund des CAP-Theorems zwischen Verfügbarkeit der Anwendung und der Datenkonsistenz gewählt werden. Monolithische Systeme können hingegen sowohl maximal verfügbar als auch maximal konsistent sein.
* Da die Microservices in unterschiedlichen Programmiersprachen und Software-Stacks implementiert werden können, werden sie das oft auch, was zu den Nachteilen des polyglotten Programmierens führt: Das Know-how kann nicht mehr geteilt werden, es erhöhen sich die Anforderungen an die Entwicklungswerkzeuge und das Plattform-Management. Zudem muss die Funktionalität von Bibliotheken teilweise dupliziert werden.

## Beispiele

Von folgenden Internetdiensten ist bekannt, dass sie Microservices benutzen:
* Google
* Amazon
* Twitter
* eBay
* Netflix
* The Guardian
* SoundCloud
* Spotify
* Zalando
* Otto