Die Microservice-Architektur ist ein Architekturmuster, bei dem eine komplexe Anwendung in übersichtliche, eigenständige Dienste (Microservices) aufgeteilt wird, die unabhängig voneinander entwickelt und deployed werden können [1].
Typischerweise kommunizieren sie über leichtgewichte APIs (z.B. HTTP). Vorteile hierbei sind, dass die einzelnen Services in verschiedenen Programmiersprachen erstellt werden können, sowie unabhängig voneinander deployable sind. Nachteilig ist der erhöhte Aufwand für das Debugging, sowie der Overhead für die Remote Calls.
Oft wird jeder Service im Sinne des Domain-driven Designs entwickelt. Im Gegensatz zu anderen Entwicklungsparadigmen beinhalten die Klassen des Domänenmodells nicht nur die Daten, sondern auch die gesamte Fachlogik.
Spring Cloud erlaubt einen schnelle Einstieg in die Entwicklung von verteilten Microservices mit Hilfe von Spring Boot.
Im Folgenden möchte ich die grundlegenden Bestandteile einer solchen Architektur zusammenfassen und mit Code-Snippets für Spring Boot anreichern. Ich werde mich fürs Erste auf die Komponenten fokusieren, die von Spring Cloud Netflix bereitgestellt werden:
[list]
[li type=”glyphicon-plus”]Eureka (Service Discovery)[/li]
[li type=”glyphicon-plus”]Hystrix (Circuit Breaker)[/li]
[li type=”glyphicon-plus”]Zuul (Edge Server)[/li]
[li type=”glyphicon-plus”]Ribbon (Client-side Load Balancing)[/li]
[li type=”glyphicon-plus”]Sleuth (Verteiltes Tracing)[/li]
[/list]
Weitere nützliche Dienste:
[list]
[li type=”glyphicon-plus”]Kafka / RabbitMQ (Message Broker) https://github.com/spring-cloud/spring-cloud-stream#binder-implementations[/li]
[li type=”glyphicon-plus”]Zipkin (Verteiltes Tracing von Twitter) http://zipkin.io[/li]
[/list]
Fertig ausführbare Starterprojekte für die einzelnen Komponenten kann man sich sehr leicht auf http://start.spring.io zusammenstellen.
Eureka (Service Discovery)
Damit die erstellten Microservices von den Clients gefunden werden können, wird eine zentrale Registry verwendet. Spring Cloud stellt dafür Eureka bereit.
Wir nutzen start.spring.io um uns ein Projekt für Eureka anzulegen. Dazu wählen wir bei Dependencies Eureka Server aus damit automatisch die benötigte Dependency im pom.xml für Maven eingefügt wird.
org.springframework.cloud spring-cloud-starter-eureka-server
Wir öffnen das Projekt und werfen einen Blick auf die Hauptklasse:
@EnableEurekaServer @SpringBootApplication public class EurekaService { public static void main(String[] args) { SpringApplication.run(EurekaService.class, args); } }
Wie wir sehen, ist die Annotation @EnableEurekaServer
ausreichend um die gesamte Funktionalität für die Service Registry einzubinden. Damit sich die Komponente nicht bei sich selber registriert, sind folgende Properties unter resources/bootstrap.properties einzutragen (die Datei muss selbst angelegt werden):
server.port=8761 eureka.client.register-with-eureka=false eureka.client.fetch-registry=false
Jetzt können wir über http://localhost:8761 auf die von Eureka bereitgestellte Weboberfläche zugreifen. Hier sehen wir zum Beispiel, welche Instanzen sich bereits registriert haben.
Damit Services und Clients mit Eureka kommunizieren können, muss bei diesen die Annotation @EnableDiscoveryClient
eingebunden werden:
@EnableDiscoveryClient @SpringBootApplication public class ClientApplication {
Hystrix (Circuit Breaker)
In verteilten Umgebungen mit vielen Diensten, die über Remote Calls kommunizieren, müssen wir davon ausgehen, dass der gewünschte Dienst nicht (innerhalb der gewünschten Zeit) erreichbar ist. Sobald zu viele Fehlschläge in einer bestimmten Zeitspanne eintreten (z.B. 20 Mal in 5 Sekunden), springt der Circuit Breaker [2] ein und öffnet den Circuit.
Hystrix ist so ein Circuit Breaker, der weitere Anfragen vom (überlasteten) Dienst fernhält und Fallback-Aktionen ausführt, bis der Dienst wieder erreichbar ist (Circuit closed).
In unserem Client müssen wir dazu die Annotation @EnableCircuitBreaker
hinzufügen. Hiermit wird Spring Cloud mitgeteilt, dass die Applikation Circuit Breakers verwendet. Mit dem Hystrix Dashboard wird uns desweiteren eine grafische Oberfläche zur Liveauswertung bereitgestellt.
Wir nutzen erneut start.spring.io mit den Dependencies für das Hystrix Dashboard und Config Client um uns ein Projekt zu erstellen. Die Dependency für Hystrix in Maven ist
org.springframework.cloud spring-cloud-starter-hystrix
Alles was wir machen müssen, ist die Annotation @EnableHystrixDashboard
einzufügen. Im Code sieht das dann einfach wie folgt aus.
@EnableHystrixDashboard @SpringBootApplication public class HystrixDashboardApplication {
Das Dashboard kann über http://localhost:8080/hystrix.stream aufgerufen werden. Wenn wir bei Monitor Stream den Link zu unserem Service eingeben, bekommen wir eine Liveauswertung der Anfragen (als gleitender Durchschnitt). Es bietet eine einfache Möglichkeit, zu sehen welche Dienste fehlerhaft sind.
Zuul (Edge Server)
Wir nutzen einen Edge Server Layer um die Anfragen von den unterschiedlichen Clients auf die entsprechenden Services abzubilden. Er kapselt somit den Zugriff auf das System dahinter auf einen einzigen Eintrittspunkt.
Wir nutzen hierfür Zuul (Gatekeeper) von Netflix. Zuul bietet dabei ein einfaches Load Balancing via Round Robin auf mehrere Instanzen eines Dienstes. Desweiteren können Filter (Authentifizierung, Logging, dynamisches Routing) umgesetzt werden.
In der pom.xml fügen wir
org.springframework.cloud spring-cloud-starter-zuul
hinzu. Wir aktivieren es mit der @EnableZuulProxy
Annotation.
@EnableZuulProxy @SpringBootApplication public class ZuulApplication {
[1] https://www.martinfowler.com/articles/microservices.html
[2] http://springinpractice.com/2010/07/06/annotation-based-circuit-breakers-with-spring/