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.

MicroProfile Health Check

MicroProfile Health Check

Mithilfe eines Health Checks lässt sich der Gesundheitsstatus der Microservices ermitteln. Dazu fragt der Service wiederkehrend flüchtige Werte (kurzlebig ohne Historie) ab, im Gegensatz zu Metrics, das mit kontinuierlichen und persistenten Datenströmen arbeitet. Gefüttert werden diese Gesundheitsdaten von Health-Check-Methoden, die der Anwendungsentwickler zur Verfügung stellen muss. Der Fokus liegt dabei auf einer M2M-Kommunikation, um einer containerbasierten Laufzeitumgebung die notwendigen Informationen über den Zustand der Services zu liefern. Cloud Foundry zum Beispiel ermittelt mit Health Checks den Status der Services, bei Kubernetes erfolgt dies durch die Liveness and Readiness Probes. Ungesunde Services werden beendet und eventuell durch neue Services (je nach Skalierungs-Policy) ersetzt. Mit der MicroProfile-Health-Check-Spezifikation wird der allgemeine Gesundheitsstatus über einen einzelnen REST Endpoint (/health) angeboten. Allgemein deswegen, weil mehrere Implementierungen der Health-Check-Methoden existieren können, was eine Überwachung von vorhandenen Subkomponenten ermöglicht. Dabei wird der Status der einzelnen Health-Check-Methoden zu einem Gesamtstatus zusammengefasst. Die Spezifikation unterteilt sich dabei in zwei Teile: Das Java-API zur Implementierung der Health-Check-Methoden und ein Protokoll mit Datenformat (HTTP Error Codes mit JSON-Struktur). Das Java-API zur Implementierung der Health-Check-Methoden bietet einen herkömmlichen Weg mit Interfaces und einen CDI-basierenden Ansatz an. Dazu implementieren CDI Beans das Interface org.eclipse.microprofile.health.HealthCheck und werden mit der Annotation org.eclipse.microprofile.health.Health versehen:

@Health
@ApplicationScoped
public class MyHealthCheck implements HealthCheck {
  public HealthCheckResponse call() {...}
}

Beim Aufruf des REST Endpoints /health werden alle nach dem obigen Schema implementierten CDI Beans aufgespürt und die jeweilige call-Methode aufgerufen. Das Methodenergebnis org.eclipse.microprofile.health.HealthCheckResponse dient dabei als Informationscontainer (Optional<Map<String, Object>>), der mit unterschiedlichsten Daten gefüttert werden kann:

public class MyMemoryCheck implements HealthCheck {
  @Override
  public HealthCheckResponse call() {
    // ermittle aktuelle Speicherwerte
    // aus der java.lang.Runtime
    long freeHeap = …;
    long usedHeap = …;
    return HealthCheckResponse.named("mein-memory-check")
    .withData("freier Heap", freeHeap)
    .withData("verwendeter Heap", usedHeap)
    .up().build();
  }
}

Mit named sollte ein sprechender Name gesetzt werden, mit dem Administratoren etwas anfangen können. Weiterführende Informationen über den Zustand eines Microservices kann der Entwickler mit der MicroProfile-Spezifikation Metrics erhalten.

MicroProfile Metrics

Für Microservices-Anwendungen reicht es kaum aus, nur über den Gesundheitszustand Auskünfte zu erhalten. Besser ist es natürlich, mit erweiterten Messdaten den Gesundheitsverlauf des Patienten besser einschätzen zu können. Hier kommen die Metrics ins Spiel. Hinter Metrics verbergen sich persistente Datenströme, aus denen sich eventuell ungesunde Zustände ableiten lassen. Dazu werden verschiedene Metriken erfasst und mittels Historie dieser Werte Rückschlüsse auf den Zustand des Servers oder der Anwendung gezogen. Im Grunde wird mit der MicroProfile-Spezifikation das Rad nicht neu erfunden, da die Applikationsserver, basierend auf JSR 77: J2EE Management, schon seit 2002 einige Statistiken liefern. Über eine JMX-Schnittstelle kann der Server verschiedene Messwerte (z. B. Thread-Count, Thread-Pool-Size, Heap Size, CPU Count, CPU-Last usw.) erfragen. Inzwischen werden diese Werte auch über REST Endpoints angeboten. Als Neuerung wird im Zuge der Spezifikation endlich das nachgeholt, was damals nicht vereinbart worden ist: eine einheitliche Schnittstelle, um auf diese Metriken zuzugreifen. Außerdem wird das Datenformat mittels JSON oder alternativ als Prometheus-Textformat vorgegeben. Prometheus ist eine verbreitete Open-Source-Monitoringlösung und zugleich Mitglied in der Cloud Native Computing Foundation, der u. a. auch Kubernetes angehört.

Großen Nutzen zieht der Entwickler aus den gesammelten Metriken, wenn damit proaktiv Fehlerzustände, wie z. B. wachsender Heap-Bedarf, erkannt werden und passende Gegenmaßnahmen eingeleitet werden können. Auch ein historisch gespeichertes Nutzerverhalten (z. B. CPU-Verbrauch) lässt sich dazu verwenden, proaktiv auf die drohenden Weihnachtseinkäufe zu reagieren, indem man die Microservices entsprechend skalieren lässt. Die neue Spezifikation unterscheidet drei verschiedene Arten von Metriken: base, vendor und application. Base-Metriken müssen von jedem Applikationsserver zur Verfügung gestellt werden und sind identisch auf allen MicroProfile-basierenden Applikationsservern. Diese Metriken lassen sich proprietär mit dem vendor-Scope erweitern. Falls dann noch Bedarf vorhanden sein sollte, weitere Metriken aus der Anwendung herauszulesen, lässt sich das mit application ergänzen. Zu diesem Zweck existiert ein API, das sich sehr stark an Dropwizard Metrics orientiert. Dazu werden aus der Anwendung heraus Metriken beim Applikationsserver registriert und selbst berechnet. Das Ganze wird wie gewohnt mittels CDI und passenden Annotationen dem Entwickler sehr komfortabel zur Verfügung gestellt:

{
  "application": {
    "myMetricCount": 45
  },
  "base": {
    "memory.usedHeap" : 268435456,
    "thread.count" : 27,
    "gc.%s.count" : 4
  }
  "vendor": {...}
}

Abgefragt werden diese Metriken über den REST Endpoint /metrics, der auch über Verfeinerungen wie z. B. /metrics/base, /metrics/application und /metrics/vendor verfügt. Was derzeit noch fehlt, aber sicherlich hilfreich wäre, ist eine Anzeige der Metriken zusammen mit dem Zustand der eingesetzten Fault-Tolerance-Patterns. Auf diese Weise würde der Entwickler ein zentrales und einheitlicheres Bild über den Gesundheitszustand der Microservices-Anwendung erhalten.

Fazit

Das MicroProfile-Thema hat im letzten Jahr massiv an Fahrt aufgenommen und in sehr kurzer Zeit viel auf den Weg gebracht. Der Funktionsumfang kann derzeit noch nicht voll mit anderen Frameworks wie Netflix OSS Stack oder Spring Boot/Spring Cloud mithalten. Der Abstand ist allerdings nicht mehr sehr groß und schrumpft zusehends. Vor allem der Ausblick auf die beiden MicroProfile-Spezifikationen OpenAPI und OpenTracing verspricht, vorhandene Lücken schnell zu schließen. In puncto Zeit fürs Hochfahren, Speicherplatz und Uber-JAR spielen die MicroProfile-Applikationsserver bereits in derselben Liga wie Spring Boot/Spring Cloud. Der große Themenblock Service-Discovery, Blue-Green Deployment, A/B Testing und Canary Releasing könnte komplett mit Istio gefüllt werden und hätte dadurch keinen Einfluss auf den Code des Microservice. Darüber hinaus bietet Istio auch die Möglichkeit, sich beim Thema Fault Tolerance einzubringen, da jeder Aufruf über einen Istio-Agenten (Sidecar) erfolgt. Die geplanten Anpassungen der MicroProfile-Spezifikationen bezüglich der Vorgaben aus Java EE 8 stellen sicher, dass hier keine neue Liga entsteht. Der Fokus von Java EE 8 auf „Enterprise for the Cloud“, besitzt eine breite funktionale Überlappung mit den MicroProfile-Spezifikationen. Außerdem haben schon einige Applikationsserver die MicroProfile-Funktionalitäten im Bauch.

Wie auf der JavaOne 2017 bestätigt, hat Oracle zugestimmt, Java EE zu öffnen, wodurch EE4J entstanden ist. Dort ist zu lesen: „Eclipse MicroProfile is such a project that EE4J will review as a source of innovations for incorporation into EE4J.“ Somit sollte klar sein, dass die MicroProfile-Spezifikationen sehr großes Potenzial haben, in Java EE 9 Einzug zu halten. Die Open-Source-Community ist jetzt aufgefordert zu beraten, wie die Vereinigung von EE4J und MicroProfile stattfinden soll. Bleibt also abzuwarten, wie lange das (legale) Doping wirkt und wann sich die Kontrahenten auf Augenhöhe begegnen werden.

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

avatar
4000
  Subscribe  
Benachrichtige mich zu: