Microservices

29.06.2015 4stern

Die Frage wie man skalierbare Web-Applikationen baut, steht irgendwie immer zur Diskussion. Es gibt keine Standardlösung, denn jeder Ansatz hat unterschiedliche Vor- und Nachteile. So dass immer abgewogen werden muss.

Ausgelöst durch Kollegen wurde ich auf das Thema aufmerksamer und habe mich entschieden mich etwas tiefer damit zu befassen. Im Netz stößt man auf einiges an Lektüre zu dem Thema und ich habe auch eine kleine Linkliste als Einstiegspunkte am Ende des Beitrags hinterlegt.

Das Thema ist nicht neu, und man kann sagen, dass Microservices inzwischen ein Strukturpattern geworden sind. Eine Art wie man Komponenten einer Applikation strukturiert. Laut Martin Fowler kann man Komponenten auf zwei Arten bereitstellen: als Bibliotheken oder als Services.

Bibliotheken werden in den Applikationscode eingebunden. Die Kopplung hierbei ist ziemlich stark und sie findet im selben Kontext statt, innerhalb der Applikation. Gibt es eine neue Version der Bibliothek, muss man seine Applikation gegebenenfalls anpassen. Da sich beide den selben Kontext teilen, muss man den Erfordernissen der Bibliothek genüge tun. Mit unter kann das ein Blocker für die ganze Applikation werden. Zum Beispiel wenn die Bibliothek vorher auf Java7 lief und die neue Version nur mit Java8 funktioniert. Läuft die eigene Applikation aber nur mit Java7, muss man entweder auf die neue Version der Bibliothek verzichten, oder aber meine Applikation auf Java8 umstellen. Besteht eine Applikation aus einer Vielzahl von Bibliotheken gibt es an diesem Punkt eventuell enormen Aufwand die Abhängigkeiten unter ein Hut zu bekommen!

Services hingegen sind eigenständige kleine Applikationen, Microservices. Sie stellen ihre Funktionalität nicht innerhalb der Applikation zur Verfügung, sondern über eine lose gekoppelte API. Sie teilen sich nicht den selben Kontext, jeder Service hat seinen eigenen. So können zum Beispiel unterschiedliche Java Versionen innerhalb der Applikation zum Einsatz kommen, oder unterschiedliche Programmiersprachen, Datenbanken, Frameworks oder Architekturen.

Eine Applikation die Microservices nutzt, ist also ein leichtgewichtiges Zusammenspiel aus verschiedensten lose gekoppelten Services. Jeder Service mit einer API, eigenem Code und eigenen Daten.

Welche Vorteile hat das insgesamt?

  • Unterschiedliche Kontexte
    • Erlaubt unterschiedliche Versionen, Programmiersprachen, Frameworks, Architekturen, Datenbanken
  • Kommunikation
    • Funktioniert über definierte Schnittstellen.
  • Modularität
    • Hinter jeder Schnittstelle kann das System komplett gewechselt werden.
    • Jeder teil der Applikation kann auf Services zugreifen ohne spezielle Abhängikeitenauflösen zu müssen.
  • Skalierbarkeit
    • jeder Service kann multipliziert und der Last entsprechenden skaliert werden ohne Auswirkungen auf andere Komponenten zu nehmen
  • Komplexität
    • deutlich geringer, weil es weniger Abhängigkeiten zu berücksichtigen gibt.
    • man muss das große Ganze nicht im Blick haben sondern kann den Fokus auf den Service lassen.
    • gute Vorraussetzungen für rapid Prototyping
  • Build / Deployment
    • kleinere Sourcecodes erlauben kleinere stabilere Builds, am besten innerhalb von Minuten
    • schnellere stabiliere Builds sind die Grundlage für Continuous Delivery
  • unabhängiger Betrieb
    • Services können in anderen Threads bis hin zu anderen Rechenzentren verteilt und betreut werden ohne gegenseitige Abhängigkeiten aufzubauen
  • unabhängige Entwicklung
    • die Entwicklung von Services beeinträchtigt sich nicht gegenseitig

Trotz der Vorteile gibt es Dinge über die man nachdenken muss!

  • Testing
    • End-zu-End-Tests sind für verteilte Systeme eine Herrausforderung
    • Testen sollte zum Standard gehören
  • Monitoring
    • Für den Betrieb des Gesamtsystems ist ein Mindestmaß an Monitoring ein Must-Have!
  • DevOps
    • Entwickler müssen ein stärkeres Verständis für technischen Belange des Umfeldes haben, zb Datenbanken zu deployen, optimieren etc
  • APIs
    • stärkere Kommunikation der Componenten untereinander
    • Stabilität von APIs im Griff haben

Als Best Practices können folgende Dinge gelten:

  • Jeder Service sollte seine eigenen Daten auch verwalten. Keine Zentrale Datenbank!
  • Code sollte überall einfach und möglichst auf dem gleichen Level sein!
  • Jeder Microservice sollte sein eigenes Deloyment besitzen!
  • Container helfen beim Deployment!

    Gemeint sind hier Container wie zum Beispiel Docker!

  • Treat Servers as Stateless
  • Microservices sollten so einfach wie möglich sein, um sie schnell neu zu erstellen anstatt sie zu "refactoren"!

Fazit:
Microservices eigenen sich hervorragend wenn man agil, schnell auf Änderungen reagieren muss. Man kann Teile der Applikation komplett unabhängig erstellen, testen und bereitstellen. Dennoch verlangt es einiges. Martin Fowler sagte dazu "you must be tall like this [to use microservices]", und damit hat er recht. Für kleinere Projekte ist dieses Pattern sicher nicht die richtige Wahl. Für professionelle Anwendungen mit hohen Anforderungen an Skalierbarkeit und Flexibilität ist es aber die zeitgemäße Antwort!

Nachtrag:
Martin Fowler hat zu dem Thema auch noch den Blogartikel 'Monolith First' geschrieben, in dem er beschreibt das es wohl am sichersten wäre mit einem Monolithen zu beginnen. Man kann so das System besser kennenlernen ohne den strukturellen Mehraufwand bereits leisten zu müssen. Sehr interessante Idee.

Links: