Artikel "Frühlingswolken"

Transcription

Artikel "Frühlingswolken"
Java Mag
REST und SPAs – immer die beste Lösung? 62
6.2016
magazin
Java • Architekturen • Web • Agile
www.javamagazin.de
Multilingual
React Native
Scala in AWS
Groovy-Code in Java-Applikationen 30
Native Apps mit JavaScript 70
Schritt für Schritt in die Cloud 78
e
h
c
i
l
k
c
glüJava-Entwickler
Der
© iStockphoto.com/thorbjorn66
Wenn das Hobby
zum Beruf wird
Spring Boot: Eine
frühlings­hafte Lösung
für Micro­services 56
Java 8: API-­
Design mit
Lambdas 12
Spring Cloud und Netflix
OSS: Cloud-native Anwen­
dungen bauen 87
Sonderdruck
Agile
Teil 2: Cloud-native Anwendungen bauen mit Spring Cloud und Netflix OSS
Frühlingswolken
Cloud-native Anwendungen skalieren fast beliebig, reagieren elastisch auf Last und sind
bis an die Schmerzgrenze fehlertolerant. So etwas sicherzustellen ist komplex. Es braucht
neue Frameworks und Infrastruktur, die den Anwendungsentwickler vor dieser Komplexität
schützen. Genau das leistet Spring Cloud: Es bietet ein Framework zur Entwicklung von
Cloud-nativen Anwendungen als Microservices und integriert die quelloffene Cloud-Infrastruktur von Netflix und Co.
von Dr. Josef Adersberger und Mario-Leander Reimer
Die Entwicklung und der Betrieb von Cloud-nativen
Anwendungen sollte so einfach sein wie bei traditionellen Java-EE-Anwendungen. Dennoch bringt der hohe
Verteilungsgrad viel Komplexität mit sich. Das SpringCloud-Projekt [1] verspricht hier Abhilfe: Es setzt auf
Spring Boot als Container für Microservices, integriert
vielerlei Cloud-Infrastruktur und vereinfacht in gewohnter Spring-Manier die Programmierung.
Spring Cloud ist ein Schirmprojekt über derzeit
fünfzehn Bausteinprojekte. Es ist Ende 2014 gestartet
und unserer Meinung nach die tragfähigste Basis, um
Cloud-native Anwendungen mit Java zu entwickeln.
Spring Cloud bietet alle Bausteine eines MicroserviceFrameworks, wie sie im Vorgängerartikel beschrieben
wurden [2]. Abbildung 1 zeigt, wie sich Spring-CloudBausteine auf die typischen Bausteine eines Microservice-Frameworks abbilden.
Die momentan grundlegendsten Bausteine von Spring
Cloud sind Netflix Eureka, Spring Cloud Config, Net­flix
Hystrix, Netflix Ribbon, Netflix Feign, Netflix Zuul,
Hystrix Dashboard und Netflix Turbine.
Netflix Eureka zur Service Discovery, die Registratur
für Serviceendpunkte: Microservices können ihre Endpunkte bei Eureka registrieren und nach vorhandenen
Endpunkten suchen. Ferner überwacht Eureka kontinuierlich die Verfügbarkeit der Endpunkte. Es besteht aus
einer hochskalierbaren und ausfallsicheren Serverkomponente sowie aus clientseitigen Komponenten.
Artikelserie
Teil 1: Der Cloud-Native-Stack
Teil 2: Cloud-native Anwendungen bauen mit Spring
Cloud und Netflix OSS
Teil 3: Clusterorchestrierung mit Kubernetes
Teil 4: Mesos: Das Betriebssystem der Cloud
2
javamagazin 6 | 2016
Spring Cloud Config zur Service Configuration übernimmt die zentrale Verwaltung von Konfigurationsparametern der Anwendungen über alle Umgebungen
und Stages hinweg. Es stellt dabei die Konsistenz der
Konfigurationsstände sicher und ermöglicht es, Konfigurationsparameter zur Laufzeit zu aktualisieren. Net­
flix Hystrix als Circuit Breaker im Serviceclient sorgt für
die nötige Resilienz von Serviceclients [3], [4] und sammelt Statistiken zu Fehlerquoten und Antwortzeiten. Bei
Ribbon handelt es sich um einen clientseitigen Load Balancer zur Lastverteilung zwischen mehreren Serviceinstanzen. Diese erfragt er bei Eureka. Netflix Feign, zum
einfachen Aufruf von REST-Schnittstellen im Serviceclient, verfolgt einen deklarativen Ansatz; der übliche
Boilerplate-Code bei Nutzung von Jersey oder Spring
RestTemplate entfällt. Feign macht aus einem normalen
Java-Interface plus speziellen Annotationen einen Serviceclient, der bereits mit Hystrix, Ribbon und Eureka
integriert ist. Netflix Zuul – als Edge-Server – ist das
Zugangstor zu den Endpunkten von außen. Er routet
Anfragen zum richtigen Endpunkt und sorgt dabei für
Load Balancing. Zuul holt sich die dafür notwendigen
Informationen aus Eureka und verwendet Ribbon und
Hystrix für das Dispatching der Aufrufe. Das Hystrix
Dashboard zeigt die Statistiken der Hystrix Circuit
Breaker grafisch an, Netflix Turbine ist verantwortlich,
die dafür notwendigen Daten von allen Knoten einzusammeln und zu aggregieren.
Eine vertiefende Beschreibung dieser und weiterer
Bausteine von Spring Cloud kann der Dokumentation [5] entnommen werden. Da diese teilweise sehr
knapp gehalten ist, raten wir zusätzlich zu einem Blick
in die Spring-Cloud-Beispielanwendungen [6] und, gerade wenn es um Konfigurationsparameter geht, in den
Quellcode selbst.
Spring Cloud wird in Release Trains versioniert, ähnlich dem Entwicklungsmodell von Eclipse. Damit wird
die Entwicklung in den verschiedenen Bausteinprojekten synchronisiert. Die Namen der Release Trains sind
© Software & Support Media GmbH
www.JAXenter.de
Sonderdruck
Agile
Abb. 1: Spring-Cloud-Bausteine auf typische Bausteine eines Microservice-Frameworks abbilden
Stationen der Londoner Metro: Das aktuelle Release ist
Angel, momentan in Entwicklung ist Brixton. Beim Bau
einer Cloud-nativen Anwendung muss beachtet werden,
dass die Releases von Spring Boot und Spring Cloud
kompatibel sind. So läuft Angel noch mit Spring Boot
1.2.x, wohingegen Brixton nur noch mit Spring Boot
1.3.x kompatibel ist.
Für das schnelle Erstellen von Cloud-nativen Anwendungen bietet sich Spring Initializr [7] an. Über eine
Weboberfläche können die gewünschten Bausteine ausgewählt und ein Projektgrundgerüst mit Build-Skripten
und Spring-Boot-Hauptklasse generiert werden.
Der Zwitscher-Showcase
Nun wollen wir am Beispiel von Zwitscher, unserer
Cloud-nativen Beispielanwendung, zeigen, wie Spring
Cloud genutzt werden kann. Zwitscher ist eine Webanwendung, die Meldungen aus mehreren Internetquellen
aggregiert. Abbildung 2 zeigt den schematischen Aufbau
von Zwitscher und welche Bausteine von Spring Cloud
dabei verwendet werden.
Zwitscher besteht aus zwei Microservices: Der Zwitscher-Service ruft Tweets und Quotes bei entsprechenden Onlinediensten ab und stellt sie über ein REST-API
zur Verfügung. Das Zwitscher Dashboard ist ein Web-
Abb. 2: Aufbau Zwitscher-Showcase
www.JAXenter.de
© Software & Support Media GmbH
javamagazin 6 | 2016
3
Sonderdruck
Agile
Abb. 3: Eureka-Serviceübersicht
UI, mit dem Tweets und Quotes angezeigt und durchsucht werden können. Es nutzt dafür das REST-API des
Zwitscher-Service. Um diese beiden anwendungsspezifischen Microservices herum läuft die Infrastruktur des
Microservice-Frameworks – natürlich ebenso als Microservice. Der komplette Sourcecode der Beispielanwendung steht auf GitHub [8] zur Verfügung.
Service Discovery mit Netflix Eureka
Im ersten Schritt realisieren wir die Service Discovery
auf Basis von Netflix Eureka. Für das schnelle ProjektSet-up verwenden wir Spring Initializr, wählen den
Baustein Eureka Server aus und lassen uns die Projekthülle generieren. Um die generierte Applikation in
einen lauffähigen Eureka-Server zu verwandeln, muss
man lediglich die @EnableEurekaServer-Annotation
zur Spring-Boot-Hauptklasse hinzufügen. Danach ist
Listing 1
eureka:
client:
registerWithEureka: false
fetchRegistry: false
Listing 2
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
4
javamagazin 6 | 2016
der Eureka-Server bereits lauffähig, das UI kann unter
http://localhost:8761 aufgerufen werden (Abb. 3).
Serviceübersicht in Eureka
Eureka ist auf Hochverfügbarkeit ausgelegt. Unser Server erwartet eine zweite Eureka-Serverinstanz, mit der
die Registry-Informationen repliziert werden können.
Für ein einfaches lokales Set-up ist dieses Verhalten jedoch nicht erforderlich, weshalb wir Eureka vorerst im
Standalone-Modus betreiben. Listing 1 zeigt die hierfür
notwendige Konfiguration in der Datei application.yml.
Jeder Eureka-Server ist gleichzeitig auch ein EurekaClient, da er seine Dienste über Endpunkte zur Verfügung stellt. Die obigen Parameter bringen den Client im
Server dazu, den Service nicht zu registrieren und sich
den kompletten Registry-Inhalt nicht anfänglich herunterzuladen. Damit ist sein Wunsch nach einem zweiten
Eureka-Server abgekappt.
Um später einen Service am Eureka-Server zu regis­
trieren, muss dem Projekt die spring-cloud-starter-eureka
BuildDependency hinzugefügt und die Hauptklasse mit
der @EnableDiscoveryClient-Annotation versehen werden. Daraufhin registriert sich die Anwendung unter dem
Namen, der als Property spring.application.name in der
Datei bootstrap.yml hinterlegt ist. Damit der Eureka-Client den Server findet, definieren wir den Eureka-ServiceURL in der application.yml (Listing 2). Der Parameter
defaultZone erlaubt, dass man kommasepariert auf eine
oder mehrere Eureka-Serverinstanzen verweist.
Service Configuration mit Spring Cloud Config
Die Konfigurationen der einzelnen Services können über
Spring Cloud Config zentral über einen Config-Server
© Software & Support Media GmbH
www.JAXenter.de
Sonderdruck
Agile
verwaltet werden. Eine Anwendung sucht beim Start den
Configuration Service per Service Discovery und ruft anschließend die jeweiligen Konfigurationswerte ab.
Für Zwitscher erzeugen wir per Spring Initializr einen neuen Config-Server. Die Hauptklasse wird anschließend mit der @EnableConfigServer-Annotation
versehen, um den Config-Server in die Spring-BootApplikation einzubetten. Zusätzlich annotieren wir die
Applikation mit @EnableDiscoveryClient, damit der
Config-Server später per Service Discovery gefunden
wird. Der Server stellt die Konfigurationen über eine
REST-Schnittstelle bereit. Es gibt verschiedene Möglichkeiten zur Ablage der Konfigurationsdateien: in einem
Git oder Subversion Repository oder nativ im Klassenpfad des Config-Servers. Letztere Option ist speziell zu
Beginn der Entwicklung praktisch. Listing 3 zeigt die
entsprechende Konfiguration des Config-Servers.
Alle Konfigurationsdateien werden direkt im Verzeichnis src/main/resources/config im Config-ServerProjekt abgelegt und folgen dem Namensmuster
{application}-{profile}.yml. Zu jedem Microservice können also noch verschiedene Konfigurationsvarianten
(Profile) hinterlegt werden. Dies kann man z. B. nutzen,
um unterschiedliche Parameter für die lokale Ausführung und die Ausführung in der Cloud zu hinterlegen.
Es ist natürlich nicht ratsam, sensible Daten wie Passwörter oder API Keys im Klartext in den Konfigurationsdateien zu hinterlegen. Darum bietet Spring Cloud
Config die Möglichkeit, Konfigurationswerte symmetrisch oder asymmetrisch zu verschlüsseln. Vor Auslieferung der Konfigurationsparameter an die Anwendung
werden die Werte entschlüsselt. Mehr Sicherheit bietet
nur noch ein Baustein wie Vault [9], der aber noch nicht
in Spring Cloud integriert ist.
Damit nun Anwendungen beim Start ihre Konfiguration beim Config-Server abrufen können, muss der URL
Listing 3
spring:
profiles: native
cloud:
config:
server:
native:
searchLocations: classpath:/config
Listing 4
spring:
cloud:
config:
enabled: true
discovery:
enabled: true
serviceId: ZWITSCHER-CONFIG
www.JAXenter.de
des Config-Endpunkts per Service Discovery ermittelt
werden. Listing 4 zeigt die dafür notwendige Konfiguration. Der Parameter ZWITSCHER-CONFIG ist dabei
der Servicename des Config-Servers in Eureka.
Serviceclients mit Feign, Ribbon und Hystrix
Es liegt in der Natur von Cloud-nativen Anwendungen, dass sie viel Remote kommunizieren. Es braucht
also Unterstützung dabei, schnell Serviceclients von
hoher Qualität entwickeln zu können. Die NetflixBausteine Feign, Ribbon und Hystrix, integriert mit
Spring Cloud, bieten hier eine elegante Lösung. Feign
ist ein deklarativer Web-Service-Client: Die Serviceschnittstelle wird über ein annotiertes Java-Interface
beschrieben (Listing 5). Das Interface wird mit @
FeignClient annotiert und dabei der Servicename des
Endpunkts in Eureka angegeben. Zusätzlich kann ein
Fallback Handler angegeben werden, der alle Anfragen
im Fehlerfall beantwortet. Feign kümmert sich selbstständig um die Service Discovery, und alle Anfragen an
den Endpunkt werden automatisch über einen Ribbon
Load Balancer abgesetzt und mit einem Hystrix Circuit
Breaker versehen.
Will man den Serviceclient nun nutzen, muss man
zunächst in der Spring-Boot-Hauptklasse ein paar Annotationen ergänzen (Listing 6). Zusätzlich dazu kann
auch noch die Annotation @RibbonClient verwendet
werden, um das Load-Balancing-Verhalten von Ribbon zu konfigurieren. Nun steht der Serviceclient fertig
initialisiert per Spring Dependency Injection zur Verfügung.
Der Ribbon Loader Balancer kann auch ohne Feign
im Zusammenspiel mit einem RestTemplate verwendet
werden (Listing 7). Beim Injizieren wird lediglich die
@ LoadBalanced-Annotation zusätzlich angegeben. Die
Nutzung der Instanz erfolgt wie gewohnt, mit der Ausnahme, dass der URL anstatt eines Hostnamens einen
Eureka-Servicenamen enthalten muss.
Listing 5
@FeignClient(name = "zwitscher-service", fallback = Quote.Fallback.class)
public interface QuoteRepository {
@RequestMapping(method = RequestMethod.GET, value = "/quote")
Quote getNextQuote();
}
Listing 6
@EnableDiscoveryClient
@EnableCircuitBreaker
@EnableFeignClients
public class ZwitscherBoardApplication {
//...
}
© Software & Support Media GmbH
javamagazin 6 | 2016
5
Sonderdruck
Agile
Abb. 4: Das Zwitscher Hystrix Dashboard
Edge-Server mit Netflix Zuul
Ein Zuul-Edge-Server bildet das Zugangstor zu Zwitscher. Sowohl das Zwitscher-Service-REST-API als
auch das Zwitscher Dashboard werden als Endpunkte
von Zuul exportiert und sind unter einem gemeinsamen
Basis-URL erreichbar.
Auch hier nutzen wir wieder den Spring Initializr
für einen schnelle Start und wählen dabei die folgenden Bausteine aus: Config Client, Eureka Discovery
und Zuul. Um die generierte Spring-Boot-Applikation
zu einem Zuul Proxy zu machen, muss lediglich die
@ En­ableZuulProxy-Annotation zur Hauptklasse hinzugefügt werden. Diese Annotation aktiviert neben
Listing 7
@Autowired @LoadBalanced
private RestTemplate restTemplate;
final String tweetsRibbonUrl = "http://zwitscher-service/tweets?q={q}";
Zwitscher[] tweets = restTemplate.getForObject(tweetsRibbonUrl,
Zwitscher[].class, q);
Listing 8
zuul:
ignoredPatterns: /**/admin/**
routes:
api:
path: /api/**
serviceId: zwitscher-service
stripPrefix: true
zwitscher-board: /**
6
javamagazin 6 | 2016
der Zuul-Konfiguration auch einen Eureka-DiscoveryClient und den Hystrix Circuit Breaker. Netflix Ribbon
sorgt für die Lastverteilung aller weitergeleiteten Anfragen und Hystrix für deren Resilienz.
Das Herzstück unseres Edge-Servers besteht aus
der Konfiguration von Routen. Jede Route definiert,
welches URL-Pattern an welchen in Eureka registrierten Service weitergeleitet wird. In Listing 8 sind zwei
Beispiele für Routendefinitionen zu sehen. So leitet die
api-Route alle Aufrufe unterhalb des Pfads /api/ an den
Service mit dem Namen zwitscher-service weiter. Das
Präfix (api) wird dabei abgeschnitten. Die zweite Route verwendet die kurze Notation; hiermit werden die
Anfragen an den Service mit dem Namen zwitscherboard weitergeleitet. Präfix und Servicename sind hier
gleich. Über das zuul.ignoredPatterns Property werden
Patterns definiert, die ignoriert und nicht weitergeleitet werden sollen. Alle administrativen URLs wollen
wir natürlich nicht über den Edge-Server zugänglich
machen.
Monitoring mit Hystrix und Turbine
Im letzten Schritt statten wir die Anwendung mit einem
Monitoring aus. Wir wollen den Zustand der Circuit
Breaker über alle Services hinweg überwachen. Genau
die Circuit Breaker sitzen an den neuralgischen Stellen eines Microservice-Systems. Die aufrufenden Microservices können am besten beurteilen, wie es einem
aufgerufenen Microservice geht – ob er zu viele Fehler
produziert, abgestürzt ist oder zu langsam antwortet.
Den Zustand der Hystrix Circuit Breaker aller Services
sammeln wir über Turbine zusammen und stellen sie per
Hystrix Dashboard zur Verfügung (Abb. 4).
Wie schon in den vorherigen Schritten erzeugen wir
ein neues Projekt per Spring Initialzr und wählen dabei
© Software & Support Media GmbH
www.JAXenter.de
Sonderdruck
Agile
die folgenden Bausteine: Discovery Client, Config Client, Hystrix Dashboard und Turbine.
Die Hauptklasse der Monitoringanwendung wird
danach mit den @EnableHystrixDashboard- und
@EnableTurbine-Annotationen versehen. Zusätzlich
definieren wir noch ein Request Mapping, um Anfragen
auf oder direkt an das Hystrix Dashboard weiterzuleiten (Listing 9).
Um den aggregierten Zustand der Circuit Break über
mehrere Applikationen hinweg anzeigen zu können,
muss Turbine konfiguriert werden. Wie üblich passiert
dies direkt in der Anwendungskonfiguration (Listing 10).
Über das turbine.appConfig Property wird die Liste
an Eureka-Servicenamen konfiguriert, deren HystrixZustandsdaten aggregiert werden sollen. Nach dem
Start der Applikation kann das Hystrix Dashboard direkt unter dem per server.port Property konfigurierten
Port aufgerufen werden.
Fazit und Ausblick
Der Zwitscher-Showcase zeigt, dass mit Spring Cloud
einfache Cloud-native Anwendungen schnell umgesetzt
werden können. Der Programmierstil ist in gewohnter
Spring-Manier und geht einfach von der Hand. Alle
Bausteine der Infrastruktur sind Microservices. Eine
vollständige Umgebung ist deshalb mit wenigen Kommandos schnell gestartet.
Spring Cloud macht einen reifen und runden Eindruck, wird sich aber durch die hohe Dynamik im
Bereich der Cloud-nativen Anwendungen stärker verändern, als man dies bei anderen Frameworks gewohnt
ist. So gibt es ständig neue „Treiber“-Bausteine für aufkommende Cloud-Infrastruktur. Momentan wird z. B.
gerade intensiv an einer tieferen Integration von Spring
Cloud mit Kubernetes gearbeitet. Ferner deutet sich aktuell an, dass die Bedeutung von Consul bei der Service
Discovery und der Service Configuration zunimmt. Die
hohe Dynamik merkt man der Dokumentation an. Hier
liefert ein Blick in die Beispielapplikationen oder in den
Quellcode von Spring Cloud selbst oft die besseren Antworten für Fragen abseits des normalen Trampelpfads.
Im nächsten Artikel dieser Serie werden wir Zwitscher
auf einem Kubernetes-Cluster zum Laufen bringen.
Dr. Josef Adersberger ist technischer Geschäftsführer der QAware
GmbH, einem IT-Projekthaus mit Schwerpunkt auf Cloud-native Anwendungen und Softwaresanierung. Er hält seit mehr als zehn Jahren Vorlesungen und publiziert zu Themen des Software-Engineerings,
aktuell insbesondere zu Cloud Computing.
Mario-Leander Reimer ist Cheftechnologe bei der QAware. Er ist
Spezialist für den Entwurf und die Umsetzung von komplexen System- und Softwarearchitekturen auf Basis von Open-Source-Technologien. Als Mitglied im Java Community Process (JCP) ist sein
Ziel, die Java-Plattform weiter zu verbessern und praxistaugliche
Spezifikationen zu entwickeln.
Links & Literatur
[1] Spring-Cloud-Projekt: http://projects.spring.io/spring-cloud
[2] Dr. Adersberger, Josef; Reimer, Mario-Leander; Zitzelsberger, Andreas:
„Über den Wolken“, in: Java Magazin 4.2016
[3] Wolff, Eberhard: „Resilience mit Spring Cloud“, in: Java Magazin 5.2015
Listing 9
[4] Brehmer, Gerrit: „Hystrix in Action“, in: Java Magazin 12.2015
@SpringBootApplication
@EnableDiscoveryClient
@EnableTurbine
@EnableHystrixDashboard
@Controller
public class ZwitscherMonitorApplication {
[5] Spring Cloud Reference Documentation: http://projects.spring.io/springcloud/spring-cloud.html
[6] Spring Cloud Samples: https://github.com/spring-cloud-samples
[7] Spring Initializr: https://start.spring.io
[8] Cloud Native Zwitscher Showcase: https://github.com/qaware/cloudnative-zwitscher
@RequestMapping(path = "/", method = RequestMethod.GET)
public String index() {
return "forward:/hystrix";
}
[9] HashiCorp Vault: https://www.vaultproject.io
[10] Spring Cloud Config: http://cloud.spring.io/spring-cloud-config
[11] Spring Cloud Netflix: http://cloud.spring.io/spring-cloud-netflix
public static void main(String[] args) { // ... }
}
Listing 10
turbine:
appConfig: zwitscher-service,zwitscher-board,zwitscher-edge
instanceUrlSuffix: /admin/hystrix.stream
instanceInsertPort: true
aggregator:
clusterConfig: ZWITSCHER
www.JAXenter.de
QAware GmbH
[email protected]
Aschauer Str. 32
81549 München
Tel.: +49 (0) 89 23 23 15 - 0
Rheinstr. 4D
55116 Mainz
Tel.: +49 (0) 6131 215 69 - 0
© Software & Support Media GmbH
javamagazin 6 | 2016
7

Similar documents