Spring Boot: mehrere Services lokal entwickeln
Ein Spring-Boot-Service auf deiner Maschine ist ein gelöstes Problem: du führst die Hauptklasse aus und arbeitest. Fünf, die miteinander sprechen, mit einem Kafka und einem Postgres darunter, sind der Ort, an dem der Vormittag verloren geht.
Was wirklich Zeit kostet
- Die Reihenfolge. Wer sich registriert, muss oben sein, bevor der
sucht, der ihn braucht, und „oben“ heißt, auf
/actuator/healthzu antworten, nicht eine PID zu haben. - Die Ports. Zwei Services bringen standardmäßig 8080 mit. Der dritte, den du startest, findet einen belegt, und du darfst herausfinden, welchen.
- Die URLs. Jeder Service hat eine Property, die auf einen anderen
zeigt —
app.catalog.urlund ihre fünfzehn Geschwister— und drei davon woanders hin zeigen zu lassen heißt, Dateien zu ändern, an die man dann denken muss, sie nicht zu committen. - Die Infrastruktur. Kafka, Redis und PostgreSQL, immer gleich gestartet, mit den Topics und dem Schema, die die Services erwarten.
- Deine eigenen Bibliotheken. Eine gemeinsame Bibliothek, die du
obendrein ändern musst, heißt
mvn install, Version hochziehen und darauf hoffen, dass niemand sonst den Snapshot gezogen hat.
Was Aseptic damit macht
Aseptic erkennt einen Spring-Boot-Service an seinem Manifest —Maven oder Gradle— und weiß,
wie er zu starten ist, wo sein Health-Endpunkt liegt und wie ihm Konfiguration übergeben
wird. Die Konfiguration wird beim Start injiziert, als
-D-Systemproperties oder Umgebungsvariablen, die URLs zwischen den Services
werden also umgeschrieben, ohne application.yml oder sonst etwas in deinem
Repository anzufassen. Nichts zu committen, nichts, woran man beim Zurücknehmen denken
müsste.
Ein Szenario gruppiert die Services eines Ablaufs und startet sie in Abhängigkeitsreihenfolge, wobei es auf die Health wartet und nicht auf den Prozess. Kollidierende Ports werden von selbst remappt, und der neue Wert ist der, der den anderen Services mitgeteilt wird. Kafka, Redis und PostgreSQL starten in Docker, von der App verwaltet.
Für jede Abhängigkeit wählst du, wo sie aufgelöst wird: ein anderer Service, den du lokal offen hast, eure gemeinsame Cloud-Umgebung —mit VPN, wenn ihr so hinkommt— oder ein Mock. Diese Wahl gilt pro Abhängigkeit, nicht pro Umgebung, „diese beiden lokal und der Rest gegen die Cloud“ ist also ein ganz normaler Dienstag und keine Konfigurationsübung.
Bibliotheken, ohne sie zu veröffentlichen
Wenn die Änderung einen Service und eine deiner Bibliotheken umfasst, baut Aseptic die
Bibliothek und verlinkt sie bei ihren Verbrauchern dort, wo Maven und Gradle sie suchen
—in deinem lokalen Repository ~/.m2— und kann sie bei Änderungen neu bauen und
neu verlinken. Es ändert weder die pom.xml noch die build.gradle
des Verbrauchers, und das Aufheben der Verknüpfung macht nur rückgängig, was es getan hat.
Was es nicht tut
Es ersetzt deinen Build nicht. Maven und Gradle bleiben genau, wo sie sind, und Aseptic ruft sie auf. Es führt keinen Kubernetes-Cluster aus, wenn du also eine Probe, ein Ingress oder einen Sidecar prüfen musst, ist dies das falsche Werkzeug —ein lokaler Cluster ist das richtige—. Und es braucht Docker für die gemeinsame Infrastruktur, es muss also Docker Desktop oder eine Docker-Engine installiert sein.
Es ist in öffentlicher Beta, erscheint für Windows, macOS und Linux und ist kostenlos für private Nutzung.
Wo das gegenüber den üblichen Verdächtigen steht
Wenn deine Services schon Images und Manifeste haben, die du pflegst, halten Tilt oder Skaffold die lokale Schleife in der Form der Produktion, im Tausch gegen einen Build und ein Deployment bei jeder Änderung. Die Seite Docker-Compose-Alternativen breitet das ganze Feld aus, und der breite Vergleich deckt Compose und lokales Kubernetes direkt ab.
Es gibt Entsprechungen dieser Seite für Quarkus und für Node.
Häufige Fragen
Wie starte ich mehrere Spring-Boot-Microservices lokal?
Du musst vier Dinge lösen: die gemeinsame Infrastruktur, den Start jedes Service mit seinem Profil und seinen Variablen, wohin jeder ruft, und die Daten. Was meistens schiefgeht, ist das Dritte — und genau das endet in von Hand geänderten URLs.
Muss ich die application.yml anfassen, um auf eine andere Umgebung zu zeigen?
Mit Aseptic nicht: die Konfiguration wird beim Start als -D-Properties injiziert, die Datei im Repository bleibt also, wie sie ist.
Kann ich eine eigene Bibliothek verlinken, ohne sie zu veröffentlichen?
Ja. Aseptic baut sie und verlinkt sie dort, wo Maven oder Gradle sie auflösen —im lokalen Repository ~/.m2—, ohne die Abhängigkeitsdatei des Verbrauchers anzufassen.