In diesem Blogpost soll die Thematik „Microservices mit Spring Boot und Spring Cloud“ anhand eines internen Workshops dargestellt werden. Diese Technik hat für uns eine hohe Relevanz, da wir sie zum einen in vielen aktuellen Projekten nutzen und sie zum anderen auch gut über ein Training vermittelbar ist.

Wissensvermittlung per Workshop

Das Prinzip von Workshops hat sich bei uns etabliert, da sich gezeigt hat, dass die Vermittlung von Wissen von Mitarbeitern für Mitarbeiter und das Teilen von Know-How sowohl intern in den Teams als auch extern im Kundenkontakt positiv anregend wirkt. Zudem sorgt das anvisierte 30:70 Verhältnis von Theorie und Praxis dafür, dass die selbst angewandten Inhalte besser verinnerlicht und dann später auch effektiv und eigenständig umgesetzt werden können. So bleiben wir bei der Scandio weiterhin innovativ und agil.

Inhalt und Ablauf

Im Zuge des zweiteiligen Workshops über “Microservices with Spring Boot and Spring Cloud” wurde zunächst auf die Erstellung eines Microservices mit Hilfe von Spring Boot eingegangen. Schwerpunkte des zweiten Teils bildeten der Zusammenschluss und die Kommunikation zwischen mehreren Services.

Aus technischer Sicht sind Microservices kleine Applikationen, die unter anderem folgende Eigenschaften haben:

  • Sie stellen eine einzelne, genau definierte Funktionalität zur Verfügung,
  • können eigenständig entwickelt, getestet, verteilt und betrieben
  • sowie autonom skaliert werden

Das Ziel des Workshops bestand darin, dass jeder Teilnehmer mit Hilfe von Spring Boot einen Microservice erstellen kann und diese Services im zweiten Teil dann zu einer kleinen Cloud zusammengeschlossen werden.

Spring Boot stellt eine Erweiterung des Java-basierten Spring Frameworks dar, mit dem gemäß des Zitats auf der Homepage: „Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can just run” ohne viel Aufwand und mit wenig Code ein Microservice erstellt werden kann.

Erstellung eines einfachen Microservices

Die meisten Features von Spring Boot sind in sogenannte starter-dependencies verpackt und werden durch die Einbindung in das eigene Projekt aktiviert. Sie sind sinnvoll vorkonfiguriert und können dann direkt genutzt werden. Die einfachste Möglichkeit einen Spring Boot Microservice zu erzeugen ist die Ableitung des eigenen Projekts vom spring-boot-starter-parent.

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.4.4.RELEASE</version>
</parent>

und die Einbindung der dependency spring-boot-starter-web

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Damit sind alle Voraussetzungen geschaffen, um einen kleinen Microservice mit eingebettetem Webserver (Tomcat) zu erstellen:

@SpringBootApplication
public class SomeService {
    public static void main(String[] args) {
        SpringApplication.run(SomeService.class, args);
    }
}
@RestController
@RequestMapping("/rest")
public class SomeController {
    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public ResponseEntity<String> hello() {
        return ResponseEntity.ok("Hello World!");
    }
}

Diese wenigen Zeilen sind ausreichend, um einen vollständig lauffähigen Microservice zu erzeugen. Mit dem Kommando

$ mvn spring-boot:run

kann der Service direkt gestartet werden und ist danach unter dieser Adresse erreichbar

http://localhost:8080/rest/hello

Der Microservice kann nun um mehrere Controllermethoden erweitert und mit der gewünschten Funktionalität befüllt werden. Für die weiteren im Workshop behandelten Themen verzichte ich hier auf Codebeispiele, da diese Großteils den entsprechenden Tutorials und Referenzdokumentationen von Spring Boot und Spring Cloud entnommen wurden.

Kommunikation zwischen den Services

Für die Kommunikation zwischen den Services wurde im ersten Schritt die Klasse RestTemplate verwendet, die bereits durch die dependency spring-boot-starter-web zur Verfügung stehen und den Zugriff auf andere REST-Services über HTTP erleichtern.

Das RestTemplate bietet zwar eine einfache Möglichkeit, Requests an andere Services zu schicken, ohne sich selbst um die eigentliche Kommunikation kümmern zu müssen (HTTP Client, etc.), allerdings sind die Methoden sehr generisch gehalten und sollten für den konkreten Anwendungsfall noch weiter gekapselt werden (konkrete Methoden pro Endpunkt, Typsicherheit usw.).

Eine elegantere Lösung und zudem ein erster Schritt in Richtung Cloud bietet hier das Paket spring-cloud-starter-feign. Feign ist ein deklarativer Web Service Client, mit dessen Hilfe eine Client-Klasse für den Zugriff auf einen Service erzeugt werden kann. Dazu muss lediglich ein Java-Interface definiert und mit entsprechenden Annotationen versehen werden. Aus dieser Interface-Definition erzeugt Feign dann ein Spring Bean, welches typsicher die Schnittstelle des entsprechenden Services zur Verfügung stellt.

Weiterhin bietet Feign noch einige weitere nützliche Features an, die insbesondere im Cloud-Umfeld nützlich und meist auch notwendig sind:

  • Unterstützung verschiedener Protokolle (HTTP, TCP, UDP)
  • Unterschiedliche Serialisierungs-/Deserialisierungsmöglichkeiten (JSON, XML)
  • Clientseitiges Loadbalancing
  • Fehlertoleranz (Hystrix, Circuit Breaker Pattern)

Service Discovery

Der Zugriff auf einen Service erfolgt immer über seine URL bzw. IP-Adresse. Da diese sich aber jederzeit ändern kann, benötigen die Nutzer eines Services die Möglichkeit ihn auffinden zu können. Dafür wird eine sog. Service Discovery verwendet, bei der sich jeder Service mit einem unveränderlichen Namen und seiner momentanen Adresse anmeldet. Dadurch kann die Adresse des Services erfragt und darauf zugegriffen werden. Durch diese zentrale Service Discovery ist auch eine Skalierung des Gesamtsystems möglich, da grundsätzlich auch mehrere Instanzen ein und desselben Services bei der Service Discovery bekannt sein können. Welcher Nutzer dann welche Instanz zugewiesen bekommt, wird von Faktoren wie Last, Latenz usw. abhängig gemacht.

Im Workshop haben wir als Service Discovery Eureka verwendet. Eureka ist Teil des Netflix Stacks und wie bereits auch Feign im Spring Cloud Projekt enthalten. Eureka selbst wird ebenfalls als Spring Boot Microservice implementiert und gestartet. Nutzer der Service Discovery binden den Eureka Client dann ein und konfigurieren dessen Adresse. Sowohl das RestTemplate als auch der Feign Client haben die entsprechenden Mechanismen integriert und können dann mit anderen Microservices über ihren Namen, anstatt über die Adresse kommunizieren. Das Auffinden des Services über die Service Discovery erfolgt für den Nutzer des RestTemplates/Feign Clients vollkommen transparent.

Herangehensweise und Zielsetzung

Für den Ablauf des Workshops wurden Grundkenntnisse in Java, Maven und Spring vorausgesetzt. Gearbeitet wurde mit den eigenen Laptops. Die Wissensvermittlung erfolgte über eine kurze theoretische Erklärungen bzw. Vorstellung der Technologien und einem anschließenden Praxisteil, in welchem jeder selbst einen Service implementieren sollte. Dabei bestand beispielsweise die Herausforderung darin, die unterschiedlichen Wissensstände der Teilnehmer zu berücksichtigen und auf die evtl. auftauchende Schwierigkeiten individuell einzugehen. Das Ziel für die Zukunft wäre, dass jeder Mitarbeiter einen solchen Workshop durchführt und die Themen und Lösungen zudem in noch geringerem Maße frontal und mithilfe einer Zieldefinition gemeinsam erarbeitet werden.

Sollten Sie Fragen oder Anmerkungen dazu haben, freuen wir uns gerne über Ihren Beitrag im Kommentarfeld.