Spring Native anyone?
Als je een Spring Initializr start, kan je ondertussen ook de experimentele dependency spring-native selecteren. Ook via Intellij kan je ondertussen hetzelfde doen.
Zonder in detail te treden in deze blog, kijken we even hoe we dit kunnen aanpakken en hoe snel alles opgezet is.
Laten we vlug een project opstarten soortgelijk aan het artikel dat we aan Quarkus gewijd hebben: e en eenvoudige RestController met een GetMapping, die de befaamde "Hello World" als resultaat teruggeeft.
Spring Boot default vs native
Als we deze spring boot applicatie opstarten dan krijgen we de standaard Spring Boot molen die zich in gang zet en na een slordige 3 seconden, is onze eenvoudige applicatie opgestart.
Nu laten we deze applicatie eens native compilen en zien hoeveel opstartkost we effectief winnen. Om dit te kunnen doen, gaan we gebruik maken van SDKMAN, zodat we snel van JDK's kunnen wisselen. Om native te compilen kunnen we gebruik maken van bijvoorbeeld GraalVM of de door spring zelf aangeprezen Liberica JDK. Laten we in dit geval de marketing machine volgen en gebruik maken van de Liberica NIK Utility. De NIK staat overigens voor Native Image Kit en is gebaseerd op... jawel, GraalVM.
Kijk zeker ook even naar het artikel ivm SDKMAN, wat het ding installeren en gebruiken een fluitje van een cent maakt.
Het volgende commando geeft ons alvast de nodige informatie welke versie we kunnen installeren.
Aangezien we met jdk 17 werken, kiezen we voor versie 21.3.0.r17.
Na een sdk install en sdk use is onze versie in gebruik.
Nu aangezien we reeds gebruik maakte van Spring Initializr is er in onze pom.xml reeds een profile voorzien die het mogelijk maakt om de boel native te compilen.
Na het uitvoeren van "mvn clean -Pnative -DskipTests package" vinden we dan een executable terug die native gecompileerd is. Laten we deze even uitvoeren en het effect zien.
Wat een verschil!
Docker Native Image
Laten we vervolgens een image bouwen via het commando
Via Spring Initializr is er ook een Native Buildpack klaargezet in de pom. Deze kan je terugvinden via de environment variable BP_NATIVE_IMAGE.
Opgelet: Tijdens het builden konden we wel eens een creator error krijgen zonder een echte reden te vinden in de stacktrace. Bijvoorbeeld:
Meestal komt dit door een error van de docker daemon zelf. Zorg er zeker voor dat je Docker daemon over genoeg geheugen beschikt en verhoog ook de Xmx setting in de MAVEN_OPTS indien nodig. In ons geval werd zo de error ook verholpen.
Zowel maven als de docker daemon kregen in ons geval 4 GB toebedeeld.
Dat het proces geheugenintensief is, zien we verschillende malen terugkomen als volgt:
[INFO] [creator] Please ensure more than 3.25GB of memory is available for Native Image
[INFO] [creator] to reduce GC overhead and improve image build time.
Als we nu onze container opstarten, zal je inderdaad vliegensvlug je container zijn opstarten met je spring boot applicatie erin. Dit alles in een fractie van een seconde!
...
2022-02-24 13:09:52.428 INFO 1 --- [ main] b.o.s.SpringNativeApplication : Started SpringNativeApplication in 0.037 seconds (JVM running for 0.039)
We kunnen niet wachten tot de eerste final release voor handen is!
Referenties
- Photo by zhang kaiyv from Pexels
- Spring Initializr - https://start.spring.io
- Liberica NIK - https://bell-sw.com/pages/liberica-native-image-kit/
- Spring Native - https://docs.spring.io/spring-native/docs/0.11.2/reference/htmlsingle/
- SdkMan To The Rescue - https://www.one16.be/blog/sdkman-rescue
- Docker, Spring Boot en Quarkus - https://www.one16.be/blog/docker-spring-boot-quarkus