Der Umstieg auf Microservice-Architekturen und zunehmend kleiner werdende Deployment- und Betriebseinheiten bringt nicht nur Vorteile. In der verteilten Cloud-Welt müssen eine Reihe von Herausforderungen adressiert werden. Dabei trifft man auch auf altbekannte Probleme, z.B. auf die Frage "Wie lautet die aktuelle Ziel-Adresse für meinen Service-Aufruf?"
Das hat man in klassischen SOA-Architekturen schon einmal gelöst, dennoch erfordern die neuen Betriebsmodelle teilweise konzeptionell und technisch andere Lösungen. Viele Technologien sind Open-Source, entwickeln sich schnell unter der Federführung von Cloud-zentrierten Unternehmen weiter und sind bereits in Enterprise-Frameworks wie Spring integriert.
Dabei ist es nicht immer einfach, im Framework-Dschungel den Überblick zu behalten. Das folgende Cheat-Sheet fasst die Frameworks und deren Rollen aus dem Spring Cloud & Netflix-Ökosystem mit dem Fokus auf synchroner Service-Kommunikation kurz zusammen.
Service-Registry: Eureka
Um einen Aufruf abzusenden, kann der Client bei der Service-Registry die aktuell verfügbaren Instanzen und deren physische Adressen (z.B. DNS-Name oder IP) eines bestimmten Services abfragen. Werden neue Instanzen hochgefahren oder bestehende Instanzen abgeschaltet, wird die Service-Registry automatisch entsprechend aktualisiert. Für Eureka gibt es eine Spring-Integration im Spring Cloud Projekt.GitHub-Link: https://github.com/Netflix/eureka
Client-Side Load-Balancing: Ribbon
Typischerweise meldet die Service-Registry mehrere laufende Instanzen. Mittels Client-Side Load-Balancing können die Aufrufe nun zufällig auf die aktiven Instanzen (ggf. nach Verfügbarkeitszone) verteilt werden, damit kein zentrales Load-Balancing zum neuen Flaschenhals wird. Ribbon ist das passende Projekt aus dem Netflix bzw. Spring Cloud-Stack.Github-Link: https://github.com/Netflix/Ribbon
API-Gateway / Proxy: Zuul
Aufrufe von außen möchte man typischerweise gebündelt und kontrolliert über ein API-Gateway auf die interne Microservice-Landschaft leiten. Zuul - ebenfalls aus dem Netflix bzw. Spring-Cloud-Stack - bietet dynamische Routing-Funktionen (angebunden an Eureka), Monitoring, Authentifizierungs- und Sicherheitsfeatures.GitHub-Link: https://github.com/Netflix/Zuul
Circuit-Breaker: Hystrix
In einer Microservice-Architektur bestehen typischerweise Abhängigkeitsketten zwischen mehreren Microservices, d.h. ein eingehender Request trifft auf den ersten Microservice, dieser benötigt Informationen von einem zweiten Microservice usw. Fällt ein Dienst "hinten" in der (synchronen) Aufrufkette aus, warten die Vorgänger auf Timeouts, blockieren viele Ressourcen und sind vermutlich ebenfalls nicht mehr funktionsfähig. Hystrix implementiert das so genannte "Circuit Breaker Pattern" - in solchen Fällen wird die Verbindung gekappt und Aufrufe werden erst wieder zugestellt, wenn der verursachende Service wieder online ist. In der Zwischenzeit können sich die vorgelagerten Microservices potenziell mit Fallback-Implementierungen (z.B. gecachten Werten) behelfen. GitHub-Link: https://github.com/Netflix/Hystrix
Dashboard für Hystrix: Turbine
Zwar bringt Hystrix bereits ein Dashboard mit, jedoch zeigt dieses immer nur den Status des Circuit-Breakers einer einzelnen Service-Instanz an. Mit Turbine lassen sich die Hystrix-Streams von den laufenden Instanzen des gleichen Microservices aggregieren und gebündelt darstellen.GitHub-Link: https://github.com/Netflix/Turbine
Deklarativer REST-Client: Feign
Für REST-Aufrufe gibt es aus dem Spring-Ökosystem im Wesentlichen zwei Ansätze: REST-Templates und deklarative Feign-Clients. Letztere sind an das Konzept von JPA-Repositories angelehnt, d.h. man definiert nur ein Interface mit passenden Methoden und muss sich nicht um die eigentliche HTTP-Kommunikation kümmern. Insbesondere REST-Aufrufe einer HATEOAS-API (Hypermedia as the Engine of Application State), wie sie bspw. Spring Data REST als Standard verwendet, können durch den integrierten HATEOAS-Support in Feign sehr einfach umgesetzt werden.GitHub-Link: https://github.com/OpenFeign/feign
Tracking von Aufrufen: Spring Sleuth und Zipkin
Die Fehlersuche in verteilten Architekturen kann durchaus kompliziert sein. Während eine Zusammenführung der dezentralen Logs unerlässlich ist (z.B. mit dem ELK-Stack), kann ein Tracing einzelner Aufrufe sowohl für das Debugging von Einzelfällen als auch bei Performance-Analysen wichtige Erkenntnisse bringen. Mit Zipkin können Requests in verteilten Architekturen gemäß dem Open-Tracing-Standard verfolgt und ausgewertet werden. Im Zusammenspiel mit Spring Sleuth sind die Request/Tracking/Span-IDs auch in den jeweiligen Log-Files zu finden. So können Zusammenhänge in verteilten Log-Files aus unterschiedlichen Microservices viel besser erkannt werden.GitHub-Link: https://github.com/openzipkin/zipkin
Zentrale Konfiguration: Spring Cloud Config Server
Um eine zentrale Konfiguration der Microservices zu ermöglichen, kann der Spring Cloud Config Server genutzt werden. Er stellt ein einem Repository (z.B. Git) versionierte Properties-Dateien über einen HTTP-Server bereit. Über Message Queues wie Kafka oder RabbitMQ können Änderungen der Konfigurationsdateien auch ohne Neustart an laufende Anwendungen verteilt werden.Alle genannten Technologien funktionieren übrigens prima mit Spring Boot! Los geht‘s auf https://start.spring.io/.
Autoren: Sebastian Sirch und Christian Siebmanns
Gerne zeigen wir Ihnen die Funktionsweise auch in einem Showcase - kontaktieren Sie uns für eine Web-Session oder einen Experten-Chat.
Mehr lesen:
JAVA CLOUD READY — SPRING NATIVE FÜR DIE ÜBERHOLSPUR
Java und Spring gehören zu den etabliertesten Technologien für Unternehmensanwendungen. In Cloud-Umgebungen stehen sie jedoch oft aufgrund von langen Startzeiten und hohen Ressourcenverbräuchen in der Kritik. In diesem Blogpost lichten wir die "Wolkendecke" rund um Spring Native, beschreiben Herausforderungen und decken Potentiale auf. Zum Artikel Java Cloud Ready – Spring Native für die Überholspur.
zurück zur Blogübersicht