Dieser Post ist eine Gegenposition zu Bene’s Talk Warum Quarkus.io geiler ist als Spring! bei code.talks und beim DevOps Stuttgart Meetup. Daher bitte ich auch den flapsigen Titel zu entschuldigen.
Quarkus.io ist ein relativ neues Framework, (laut eigener Aussage) optimiert, um Java Anwendungen Cloud Native (das bedeutet in der Praxis: in einem Kubernetes-Cluster) laufen zu lassen. Es setzt dazu insbesondere auf GraalVM und die integrierte Substrate VM.
Bene postuliert in seinem Talk im Wesentlichen:
- Spring Boot Services sind keine echten Microservices, weil zu schwergewichtig
- Weil: Die Startup-Zeit ist zu lang
- Und: Der Memory-Verbrauch ist zu hoch
Quarkus kann durch die Ahead-of-time Compilierung ein natives Image bauen, welches dann innerhalb von Millisekunden bei etwa halben Speichververbrauch läuft. Dieses Image kann in Kubernetes Umgebungen wie Knative serverless genutzt werden.
Das stimmt auch.
Jetzt kommt das ABER:
Antwortzeit ist wichtiger als Startup-Zeit
Die meisten Business-Anwendungen laufen dauerhaft, ohne extrem kurzfristige Skalierungsanforderungen. So gut wie alle Anwendungen haben eine Connection zur Datenbank oder anderen Diensten per HTTPS. Der Aufbau einer Datenbank- oder TLS-Connection ist sehr zeitaufwändig. Diese Zeit muss bei einem Kalt-Start einer Serverless-Anwendung berücksichtigt werden. Eine längerlaufende Anwendung kann im Gegensatz dazu auf einen Connection-Pool zurückgreifen, und Anfragen so deutlich schneller beantworten.
Klassische Java-Anwendungen haben im Vergleich zu Serverless-Anwendungen also eine geringere Latenz bei der Beantwortung von Requests.
(Man könnte noch anmerken, dass der JIT die Anwendung im Betrieb noch weiter optimiert, aber das hat nur minimalen Einfluss.)
Time-to-Deployment ist wichtiger als Startup-Zeit
Der Substrate AOT-Compile-Schritt dauert bei komplexeren Anwendungen mehrere Minuten, um ein natives Image zu bauen. Bei kritischen Bugs ist die gesamte Dauer von Commit zu Production-Deployment wichtiger als die alleinige Startup-Zeit der Anwendung.
Wenn ich durch den Compile-Schritt bei Quarkus also mehrere Minuten verliere, dann bringen mir die eingesparten 5 Sekunden Startup-Time der Anwendung auch nicht mehr viel.
Warum doch Spring?
OK, wir haben festgestellt, dass native Images in vielen Anwendungsfällen keinen Vorteil haben. Natürlich kann ich Quarkus Anwendungen auch klassich im OpenJDK laufen lassen.
Wie sieht es sonst im Vergleich aus?
Spring Data und Spring Security
Das Spring Framework hat wichtige, ausgereifte Features, die hervorragend mit Spring Boot integriert sind. Ich möchte an dieser Stelle nur zwei nennen:
Spring Data ist großartig und hat die Art und Weise revolutioniert, wie Datenbanken angesprochen werden. Die Quarkus-Alternative Panache ist vielversprechend, hat aber viele Features noch nicht umgesetzt.
Spring Security enthält alle wesentlichen Features, für die Absicherung komplexer Anwendungen. Die Security-Features von Quarkus sind mit Basic Auth und JWT noch sehr eingeschränkt.
Dokumentation und Stackoverflowbility
Die Dokumentation von Spring ist nicht super, aber vollständig. Bei Quarkus gibt es nur eine handvoll Tutorials. Gerade zu Datenbank-Clients und Security fehlen oft die Details.
Wie sieht es mit der Community aus?
- Stackoverflow hat zu quarkus 391 Beiträge.
- Stackoverflow hat zu spring-boot 74.516 Beiträge.
Wann würde ich Quarkus empfehlen?
Zugegeben: Redhat/IBM hat mit Quarkus vieles richtig gemacht und ein solides Framework erschaffen. Durch die Verwendung der Java/Jakarta EE Libraries werden sich bisherige Java EE Entwickler beim Umstieg leicht tun.
Meine Empfehlung lautet daher: Wer bisher mit Java EE gearbeitet hat, für den ist Quarkus genau das Richtige. Wer sich mit Spring wohl fühlt sollte auch bei Spring bleiben. Ich gehe davon aus, dass die Unterstützung für Graal, sofern sinnvoll, auch für Spring kommen werden.
Wenn Cloud Native, dann Go
Anwendungen in einer Serverless-Architektur bzw. Cloud-Native-Umgebungen würde ich persönlich eher in Go implementieren. Go ist einfach zu lernen, reduziert und bringt doch alles notwendige für die Backend-Entwicklung mit. Go Anwendungen werden direkt (innerhalb Sekunden) kompiliert, können einfach in ein minimales Docker-Image gepackt werden und werden innerhalb von Millisekunden ausgeführt.
Aber auch hier gilt: Die Wahl einer Programmiersprache oder eines Frameworks ist in der Regel nicht erfolgsentscheidend. Das Entwicklungsteam bekommt das schon hin.