© bitt24/Shutterstock.com
Enterprise Java fit für die Implementierung von Microservices machen

Doping für Microservices


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.

Video: Brauchen wir noch Java EE?

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. 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 aktuelle Release, pünktlich zum Start der JavaOne 2017, ist MicroProfile 1.2, das für den 30.09.2017 freigegeben worden ist. 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. Mit MicroProfile 1.3 (mit Kompatibilität zu Java EE 8: MicroProfile 2.0) soll in diesem Jahr eine Erweiterung des Funktionsumfangs um OpenTracing 1.0 und OpenAPI 1.0 kommen. Außerdem sind noch kleinere Updates vorgesehen, die aus dem Feedback von MicroProfile 1.2 resultieren.

Mit MicroProfile 2.0, das zeitgleich zu MicroProfile 1.3 erscheinen soll, werden die notwendigen Anpassungen bezüglich der neuen Vorgaben aus Java EE 8 umgesetzt. 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“ [1]. Weitere MicroProfile-Releases sind derzeit offiziell noch nicht in Planung.

Mit MicroProfile Config Werte zusammenführen

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<Integer> 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 ...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang