Doping für Java-EE-basierende Microservices

So werden Java-Anwendungen fit für Microservices

Michael Hofmann

©Shutterstock / bitt24

Die Implementierung von Microservices bringt einige neue Herausforderungen mit sich. Als Architekt muss man sich deswegen verstärkt mit der Anwendungskonfiguration, Resilienz und Fehlertoleranz (aufgrund des Kommunikationsverhaltens der Microservices untereinander) sowie Security und Laufzeitüberwachung beschäftigen, um nur ein paar Anforderungen zu nennen. Um die Implementierung auch mit Java-EE-Mitteln zu ermöglichen, wurde die MicroProfile-Community gegründet.

Doping für Java-EE-basierende Microservices

MicroProfile hat sich zum Ziel gesetzt, Enterprise Java und somit Java EE fit für die Implementierung von Microservices zu machen. Dazu hat sich eine mächtige Community zusammengeschlossen, die u. a. aus IBM, Red Hat, Tomitribe und Payara besteht. Mittlerweile hat MicroProfile als Projekt seinen Weg in die Eclipse Foundation gefunden und untersteht damit der Apache License 2.0. Man kann hier von legalem Doping sprechen, da bereits im Releaseplan der Community vorgesehen ist, die eventuell notwendigen Anpassungen an MicroProfile vorzunehmen, um mit der kommenden Java-EE-8-Spezifikation kompatibel zu bleiben. Eine gewünschte Mitwirkung kann einfach über den Button JOIN THE DISCUSSION auf der Startseite erfolgen.

MicroProfile – Releaseplan

Mit MicroProfile 1.0 wurde am 17.09.2016 ein erstes offizielles Release veröffentlicht. Um die Latte am Anfang nicht zu hoch zu legen, hatte man sich vorerst nur auf folgende APIs geeinigt: JAX-RS 2.0, CDI 1.2 und JSON-P 1.0. Das sind im Grunde APIs, die jeder der beteiligten Java-Applikationsserver (Red Hat WildFly Swarm, IBM Liberty Profile, Tomitribe, Payara) von Haus aus schon mitbringen musste, um Java-EE-kompatibel zu sein. Entsprechend der Meinung der Community war das ein Minimalset an APIs für die Entwicklung von Microservices. Dass dies noch lange nicht reichte, war allen Beteiligten klar, und so begann man, neue APIs zu entwerfen.

Am 21.07.2017, nach längerer Durststrecke, wurde endlich MicroProfile 1.1 veröffentlicht. Inhaltlich wurde MicroProfile 1.0 um die neue API-Config 1.0 erweitert. Auch dieser Schritt war noch nicht der große Wurf, aber inzwischen hat die Community fleißig an neuen APIs gearbeitet. Jetzt, gegen Ende des Jahres, kommt richtig Schwung in das Projekt. Das Release MicroProfile 1.2 wurde am 30.09.2017 freigegeben. Der Inhalt basiert auf MicroProfile 1.1 und folgenden neuen Spezifikationen: Config 1.1 (kleinere Updates gegenüber Config 1.0), Fault Tolerance 1.0, JWT Propagation 1.0, Health Check 1.0 und Health Metrics 1.0.

Aktuell erschienen ist MicroProfile 1.3, das eine Erweiterung des Funktionsumfangs um OpenTracing 1.0 und OpenAPI 1.0 bietet. Außerdem sind noch kleinere Updates enthalten, die aus dem Feedback von MicroProfile 1.2 resultieren.

Mit MicroProfile 2.0 sollen dann die notwendigen Anpassungen bezüglich der neuen Vorgaben aus Java EE 8 umgesetzt werden. So soll sichergestellt werden, dass der bisherige Funktionsumfang (Inhalt von MicroProfile 1.3) mit Java EE 8 lauffähig ist. Die bisherigen MicroProfile-APIs sind alle mit Java EE 7 verwendbar, daraus ergibt sich natürlich, dass alles an APIs verwendet werden kann, das in Java EE 7 und weiteren Versionen enthalten ist (z. B. JPA, EJB, JMS …). Wer als Architekt oder Entwickler noch weitere Anregungen zur Implementierung der Microservices mit Java EE sucht, sei an dieser Stelle auf IBM Redbooks verwiesen: „Microservices Best Practices for Java“. Weitere MicroProfile-Releases sind derzeit offiziell noch nicht in Planung.

MicroProfile Config

Derzeit existieren eine Menge unterschiedlicher Laufzeitumgebungen (z. B. Docker, Kubernetes, Cloud Foundry …), die eine sehr gute Basis bilden, um Microservices-Anwendungen mit ihren hohen Laufzeitanforderungen, wie z. B. automatische Skalierbarkeit, zu betreiben. Aus Sicht des Entwicklers sollte es aber egal sein, auf welcher Stage (Entwicklung, Test, QS, Produktion) sich sein Microservice gerade befindet und somit welche Umgebung dort verwendet wird. Für ihn ist es in erster Linie wichtig, dass die Werte in der Anwendungskonfiguration passend gesetzt sind und ausgelesen werden können. Dabei werden erfahrungsgemäß einige Werte der Anwendungskonfiguration auf den verschiedenen Stages neu gesetzt oder überschrieben. MicroProfile Config bietet die Möglichkeit, Werte aus verschiedenen Quellen (Prozessvariablen aus der Systemumgebung, Java System Properties und Anwendungs-Properties) zu einem Satz an Config-Werten zusammenzuführen.

Dabei werden diese Quellen mit einer Gewichtung (Ordinal) versehen, sodass eine Überschreibungshierarchie möglich ist. Es gilt das Prinzip, dass Werte mit einer höheren Ordnungszahl Werte mit einer niedrigeren überschreiben. Der Defaultwert von Anwendungs-Properties liegt bei 100. Environment-Variablen liegen bei 300, und Java System Properties haben ein Ordinal von 400. Das heißt weiter außen (außerhalb der Anwendung) liegende Config-Werte überschreiben somit die Werte innerhalb der Anwendung. Auf diese Weise lassen sich Stage-konforme Anpassungen vornehmen. Das geht sogar so weit, dass auf eine Veränderung von Werten aufgrund eines externen Events ohne Neustart des Anwendungsservers innerhalb der Anwendung reagiert werden kann.

Anwendungskonfigurationsdateien werden per Default unter dem Pfad META-INF/microprofile-config.properties in allen vorhandenen Modulen gesucht. Der Zugriff auf die Applikations-Property myserver.customer.url = https://testserver/service1/customer kann auf zwei Arten erfolgen. Entweder programmatisch:

Config config = ConfigProvider.getConfig();
String customerUrl = config.getValue("myserver.customer.url", String.class);

oder mittels Injection unter Angabe eines Defaultwerts:

@Inject
@ConfigProperty(name="myserver.customer.url", defaultValue="https://defaultServer/service1/customer")
private String customerUrl;

Fehlende Config-Werte (ohne Defaultangaben) werden mit einer Exception quittiert und verhindern den Start der Anwendung. Als optional gekennzeichnete Config-Werte (falls so etwas benötigt wird) können weggelassen werden, ohne dass eine Exception geworfen wird:

@Inject
@ConfigProperty(name="config.optvalue")
private Optional optValue;

In Microservices-Anwendungen ist es durchaus üblich, dass Config-Werte dynamisch verändert werden müssen, z. B. bedingt durch Blue Green Deployments. In diesem Fall kann der Entwickler mithilfe von javax.inject.Provider das dynamische Nachlesen des Config-Werts erreichen:

@Inject
@ConfigProperty(name="myserver.customer.url")
private Provider<String> customerUrl;

Bei jedem Aufruf von customerUrl.get() wird der aktuelle Wert aus der jeweiligen Konfigurationsquelle nachgelesen. Sollte die Notwendigkeit bestehen, gewisse Config-Werte mit einem anderen Ordinalwert zu versehen, so kann dieser in der Property-Datei angegeben werden:

config_ordinal=150
myserver.customer.url = https://testserver/service1/customer

Mit config_ordinal=150 werden die Config-Werte innerhalb der gesamten Datei mit einem Ordinalwert von 150 gewichtet. Zur Erreichung einer stärkeren Typisierung der Config-Werte werden sog. Converters im API mit angeboten, wobei sich das Spektrum mittels Custom Converters erweitern lässt. Auch hier ist wieder eine Priorisierung der Converters möglich (Converters des API haben den Wert 1).

Manche Microservices-Anwendungen verwenden einen zentralen Konfigurationsdienst (z. B. Netflix Archaius), eine Konfigurationsdatenbank oder haben die Notwendigkeit, die Config-Werte aus ganz anderen Quellen zu ermitteln. Auch dafür bietet MicroProfile Config mehrere Möglichkeiten. Mittels einer Config Source, die auf dem Prinzip des java.util.ServiceLoader basiert, lassen sich eigene Konfigurationsquellen registrieren. Sollten diese Config Sources sich obendrein noch dynamisch verändern, so kann darauf mittels eines Config-Source-Providers reagiert werden. Die angebotenen Konfigurationsmöglichkeiten sollten zusammen mit den eigenen Config-Source-Definitionen ausreichend sein. Es könnte sinnvoll sein, die Spezifikation um eine URL-Ressource als Standardquelle zu ergänzen, um alle Wünsche zu erfüllen.

Geschrieben von
Michael Hofmann
Michael Hofmann
Michael Hofmann ist freiberuflich als Berater, Coach, Referent und Autor tätig. Seine langjährigen Projekterfahrungen in den Bereichen Softwarearchitektur, Java Enterprise und DevOps hat er im deutschen und internationalen Umfeld gesammelt. Mail: info@hofmann-itconsulting.de
Kommentare

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu: