#WISSENTEILEN
Supersonic Java
für die Cloud
Quarkus
#WISSENTEILEN
@_openKnowledge | @mobileLarson
Lars Röwekamp | open knowledge GmbH
ÜBER OPEN KNOWLEDGE
Branchenneutrale Softwareentwicklung & IT-Beratung
ÜBER MICH
Wer bin ich - und wenn ja, wie viele?
• CIO New Technologies
• Enterprise & Mobile
• Autor, Speaker, Coach & Mentor
• Snowboard & MTB Enthusiast (a.k.a. “stets bemüht“)
Lars Röwekamp (a.k.a. @mobileLarson)
„Cloud native, yeah! “
Die ganze Welt
Die ganze Welt:
„Cloud native, yeah!“
Enterprise Java
„Hold my beer!“
Seien wir doch
mal ehrlich …
Seien wir doch
mal ehrlich …
kube-apiserver
kube-scheduler
kube-controller-mgr
kublet
kube-proxy
Kubernetes Cluster (in private / public / hybrid Cloud)
Control Pane Compute Machines
etcd
Container Runtime
Pod
Containers
Persistence
Storage
Container
Registry
Seien wir doch mal ehrlich …
Bedarf in Zeiten von Cloud & Co.
• klein aka niedriger Speicherbedarf
• schnell aka geringe Startup Time
• flexibel aka Modularisierung
Seien wir doch mal ehrlich …
Enterprise Java ist eher
• groß aka hoher Speicherbedarf
• langsam aka lange Startup Time
• unflexibel aka alles oder nix*
* gilt selbst für das stark abgespeckte WebProfile?
Seien wir doch mal ehrlich …
Seien wir doch mal ehrlich …
Fazit aka „Die bittere Wahrheit“
Enterprise Java ist
• noch immer relativ schwergewichtig*
• auf EINE Runtime zugeschnitten
• nicht für Microservices & Cloud konzipiert
* die Betonung liegt auf „relativ“!
„Ich will aber
mitspielen!“
Aber ist das wirklich ein Problem?*
Enterprise Java ist
• stabil
• verbreitet
• standardisiert
• btw: erstes E in JEE steht für Enterprise
* Warum nicht einfach auf verzichten?
„Gutes“
beibehalten
„Schlechtes“
über Bord werfen
„proprietäre APIs“
Variante #1
Variante: proprietäre APIs
Spezielle APIs für (Micro)Services & Cloud
Embedded lightweight Runtime als „Server“
Javalin „Hello World“
eigene
APIs
embedded
„Server“
Javalin „REST Service“
Server
Bootstraping
REST
Support
~ 250 ms / 5 MB
Variante: proprietäre APIs
PRO
• spezialisiert
• schmal
• schnell
CONS
• proprietär
• eingeschränkt*
• Micro* vs. Makro
* stark abhängig von dem jeweiligen Framework
„weniger ist mehr“
Variante #2
Variante: weniger ist mehr
Standard APIs für Microservices
Weglassen von „unnötigen“ APIs
Optionale Erweiterungen für alles Weitere
Meecrowave „Hello World“
eigene APIs
+ embedded Server
JAX-RS
Meecrowave „Hello World“
pure JAX-RS
$ mvn package meercowave:run
Meecrowave „REST Service“
pure CDI / JAX-RS*
* plus JSON-B
& JSON-P
~ 450 ms / 10 MB
#WISSENTEILEN
MicroProfile „Hello World“
pure JAX-RS
$ java –jar helloWorld-fat.jar
MicroProfile „REST Service“
pure JEE APIs
MicroProfile
Health Check
via @Readiness
MicroProfile
Metrics
via @Timed
MicroProfile
Fault Tolerance
via @Timeout
MicroProfile
JWT Auth
via @Inject & @Claim
MicroProfile
JWT Auth
via @RolesAllowed*
*pure JEE
~ 1600 ms / 80 MB
Variante: weniger ist mehr
PRO
• Standards
• Micro & Makro
• schmal*
• schnell*
• flexibel
CONS
• Bootstrapping
• je mehr, desto* …
* ist stark abhängig von den eingebundenen APIs
Zwischenfazit
Enterprise Java
in Zeiten von
Cloud & Co …
Enterprise Java in Zeiten von Cloud & Co ….
STANDARD
PROPRITARY
SLOW
FAST
Enterprise Java in Zeiten von Cloud & Co ….
STANDARD
PROPRITARY
SLOW
FAST
You are here …
! FAST but
PROPRITARY
Enterprise Java in Zeiten von Cloud & Co ….
STANDARD
PROPRITARY
SLOW
FAST
… or here
! STANDARD
but kinda
SLOW
You are here …
! FAST but
PROPRITARY
Enterprise Java in Zeiten von Cloud & Co ….
STANDARD
PROPRITARY
SLOW
FAST
… or here
!
You are here …
! FAST but
PROPRITARY
…but you want
to be here! ? STANDARD
and FAST
STANDARD
but kinda
SLOW
Wünsch dir
was …
Cloud native
• klein, schnell, flexibel
Enterprise Java
• standard, mächtig, stabil
Wünsch dir was …
„Was genau war
noch einmal
das Problem?“
„I started thinking about my application’s performance—in this case,
the bootstrap time—and asked myself whether I was happy
with the actual time my application took to start up. The answer was no.
And, nowadays, this is is one of the most important
metrics to be considered when working with
microservices, mainly on a serverless architecture.“
Filipe Spolti, Red Hat
Aus der Rubik: „Spaß beim Startup …“
internal
once
element
Metadata
Processing
at Startup
Aus der Rubik: „Spaß beim Startup …“
„Voodoo“
aka Quarkus
Lösungsansatz #3
Die vier Quarkus
Voodoo Regeln
„Build-Time
Optimization“
Voodoo #1: be small and fast
Quakus Voodoo #1
Build-Time Optimization
Ein Großteil der „möglichen“ Dynamik zur
Laufzeit wird gar nicht benötigt. Daher lässt
sich die Auflösung deren Abhängigkeiten in
die Compile-Time verschieben.*
*@Inject, @Observes, @Path, @GET, …
.java
(plus dependencies)
.class
(regular)
(1) compile (2) run on JVM
.java
(plus dependencies)
.class
(regular)
.class
(optimzed)
(1) compile (2) optimize (3) run on JVM
* plus 16 MB /lib
~ 800 ms / 12 KB*
Quarkus
PROD
Mode
./mvnw package
FASTJar
Classloader
(since version 1.12)
> java -jar target/quarkus-app/quarkus-run.jar
73 MB 136 MB
REST
Voodoo vs. Traditional:
Memory (RSS)
Quarkus + JVM
(via OpenJDK)
Traditional Stack
(cloud native)
145 MB 209 MB
REST
+ CRUD
Voodoo vs. Traditional:
Memory (RSS)
Quarkus + JVM
(via OpenJDK)
Traditional Stack
(cloud native)
Voodoo vs. Traditional:
Boot & First Response
0.94s
4.3s
0 1 2 3 4 5 6 7 8 9
REST
Quarkus + JIT (via OpenJDK)
Traditional Stack (Cloud-native)
2.0s
9.5s
0 1 2 3 4 5 6 7 8 9
REST
+ CRUD
Voodoo vs. Traditional:
Boot & First Response
Quarkus + JIT (via OpenJDK)
Traditional Stack (Cloud-native)
„Ahead-of-Time
Compilation“
Voodoo #2: be even smaller and faster
Quarkus Voodoo #2
Ahead-of-Time Compilation
„Write once, run anywhere“ ist in Zeiten von
Containern und damit einheitlichen Laufzeit-
umgebungen optional.*
*Ahead-of-Time Compilation statt dynamisches scannen / laden von Klassen
.java
(plus dependencies)
.class
(regular)
.class
(optimzed)
(1) compile (2) optimize (3) run on JVM
.java
(plus dependencies)
.class
(regular)
.class
(optimzed)
(1) compile (2) optimize (3) create native image
executable
(native)
~ 11 ms / 25 MB
Quarkus
NATIVE
Mode
~ 11 ms / 25 MB
Quarkus
NATIVE
Mode
12 MB 73 MB 136 MB
REST
+ CRUD
Voodoo vs. Traditional:
Memory (RSS)
Quarkus + Natice
(via GraalVM)
Quarkus + JVM
(via OpenJDK)
Traditional Stack
(cloud native)
28 MB 145 MB 209 MB
REST
+ CRUD
Voodoo vs. Traditional:
Memory (RSS)
Quarkus + Natice
(via GraalVM)
Quarkus + JVM
(via OpenJDK)
Traditional Stack
(cloud native)
Voodoo vs. Traditional:
Boot & First Response
Quarkus + Native (via GraalVM)
0.016s
0.94s
4.3s
0 1 2 3 4 5 6 7 8 9
REST
Quarkus + JIT (via OpenJDK)
Traditional Stack (Cloud-native)
0.042s
2.0s
9.5s
0 1 2 3 4 5 6 7 8 9
REST
+ CRUD
Voodoo vs. Traditional:
Boot & First Response
Quarkus + Native (via GraalVM)
Quarkus + JIT (via OpenJDK)
Traditional Stack (Cloud-native)
Aber was ist
mit WORA?
WORP* ist
dass neue
WORA!
*write once, run predictable
create native image
executable
(native)
containerize native image
docker container
(ubi/distroless)
„Minimize Development
Turnaround Time“*
Voodoo #3: spark joy for developers
* and more, e.g Quarkus Testing Framework
Quarkus Voodoo #3
Spark Joy for Developers
Das Maven Goal quarkus:dev erlaubt via
hot reaload* extrem kurze Turnaround-Zeiten
in der Entwicklung.
./mvnw package ./mvnw quarkus:dev
*hot reload
in action
~ 1200 ms / 10 KB*
* Paket besteht nur aus MANIFEST.MF (CP Info) und dev-mode-context.dat
Quarkus
DEV
Mode
„Power of
Standards“*
Voodoo #4: be convenient
* (de facto) Standards plus Quarkus Extension Framework
Quarkus Voodoo #4
Power of Standards
(Industrie)Standards als Basis nutzen bei
gleichzeitiger Möglichkeit von proprietären
Erweiterung.
.class
(regular)
.class
(optimzed)
optimize via Quarkus
optimized libraries*
(3rd party & custom)
Cloud-native?
„A Kubernetes Native Java stack tailored for
GraalVM & OpenJDK Hotspot created from
the best of breed Java libraries and standards.“
Was bedeutet das für Cloud-native?
„Container First“ Ansatz von Quarkus
• schmale Pakete == kleine Container Images
• schnelle Boot Time == sofortiges Scale-up
• geringer RSS* Speicher == mehr Container**
*RSS = resident set size (all RAM consumed by a process),
** mehr Container bei gleichem RAM
Was ist mit
Limitations?
Quarkus „Voodoo“
Limitations (GraalVM / SubstrateVM)
• Dynamic Classloading*
• Native VM Interfaces*
• Reflection*
• Dynamic Proxies*
• Class Path Resources* *muss via native-image CLI/API vorab registriert werden
(siehe auch: https://github.com/oracle/graal/blob/master/substratevm/LIMITATIONS.md)
Quarkus „Voodoo“
Limitations (GraalVM / SubstrateVM)
• Dynamic Classloading*
• Native VM Interfaces*
• Reflection*
• Dynamic Proxies*
• Class Path Resources* *muss via native-image CLI/API vorab registriert werden
(siehe auch: https://github.com/oracle/graal/blob/master/substratevm/LIMITATIONS.md)
„Brauche ich nicht!
Oder etwa doch?“
Quarkus „Voodoo“
Limitations (ArC DI / CDI)
• Conversational Scope
• Decorators
• Portable Extensions
• bean.xml ignored
• …
Fazit
Enterprise Java in Zeiten von Cloud & Co ….
STANDARD
PROPRITARY
SLOW
FAST
… or here
! STANDARD
but kinda
SLOW
You are here …
! FAST but
PROPRITARY
…but you want
to be here! ? STANDARD
and FAST
Enterprise Java in Zeiten von Cloud & Co ….
STANDARD
PROPRITARY
SLOW
FAST
… or here
! STANDARD
but SLOW
You are here …
! FAST but
PROPRITARY
STANDARD *
and FAST
!
Quarkus
aka Voodoo
Enterprise Java in Zeiten von Cloud & Co ….
Voodoo Regeln
• Support von „leading“ APIs & Frameworks
• Dependency-Auflösung zur Compile-Time
• kurze Turnaround Zeiten via Dev Mode
• native Container-Images mit GraalVM
Ok, aber
brauche
ICH das
wirklich?
„You are NOT Amazon,
Twitter or Netflix.“*
* except you are Amazon, Twitter or Netflix ;-)
Enterprise Java in Zeiten von Cloud & Co ….
Voodoo Regeln eXtended Version
• “FatJARs are evil.“
• „Layered Containers are good.“
• „Small layered Containers are even better.“
• „Small* layered native Containers are best.“
* Distroless Container Image als extreme Variante
„FATJar sind böse?
Warum das?“
„FATJars verlängern die
DEV Roundtrips unnötig.
Daher ist besser mit
mehreren unterschiedlichen
Layern zu arbeiten.“
*Don't Put Fat Jars in Docker Images:
https://phauer.com/2019/no-fat-jar-in-docker-image/
OS
JRE
app-v1.jar app-v2.jar app-v3.jar
70 MB
126 MB
63 MB 63 MB
63 MB
app-v1.jar 63 MB
DEPENDENCIES
53 MB
changes rarely
RESOURCES
8 MB
changes from
time to time
CODE
2 MB
changes frequently
OS
JRE
code-v1.jar code-v2.jar code-v3.jar
70 MB
126 MB
2 MB 2 MB
2 MB
Dependencies
Resources
53 MB
8 MB
? ? ?
#WISSENTEILEN
@mobileLarson
@_openKnowledge
Lars Röwekamp, @mobileLarson
Kontakt:
lars.roewekamp@openknowledge.de
kontakt@openknowledge.de
Besten Dank! #WISSENTEILEN
© max0380 – iStockphoto.com (Folie 1)
© Ljubco – iStockphoto.com (Folie 5)
© Orban Aljia – iStockphoto.com (Folie 6)
© foxaon1987 – Shutterstock (Folie 44)
© Framework Wonderland – Shutterstock.com (Folie 90)
Alle weiteren Bilder der Präsentation sind entweder von pexels.com,
pixabay.com oder von mir selbst erstellt.
Bildernachweis

Supersonic Java für die Cloud: Quarkus