Spring Native for GraalVM (por fin!)))

Tras estos posts sobre GraalVM en los que presentábamos GraalVM y contábamos cómo instalarlo y generar una aplicación nativa GraalVM llega el momento de ver cómo generar un ejecutable nativo GraalVM de nuestra aplicación Spring Boot.

Para esto usaremos el proyecto spring-native-graalvm que aún está en estado experimental pero ya nos permite de una forma muy sencilla generar aplicaciones nativas GraalVM de aplicaciones Spring Boot. Y el Por fin!!! es porque aunque en Spring han sido rápidos, hasta finales de 2020 no hemos tenido esta posibilidad y los pasos eran bastante más complejos, y por otro es fundamental que la tecnología Java más usada en la actualidad (Spring) tuviera soporte para crear aplicaciones nativas GraalVM más cuando otras tecnologías como Micronauy o Quarkus ya la tenían.

Empezaremos por descargarnos el proyecto de ejemplo del que partimos que no es más que un servicio REST Greeting,

para esto:

git clone https://github.com/spring-guides/gs-rest-service

cd gs-rest-service/complete

Tras esto debemos actualizar el pom.xml para usar al menos Spring Boot 2.4.1 que es la primera versión de Spring que tiene soporte para generar nativos GraalVM:

Antes de empezar con el proceso ejecutaremos la aplicación original, para eso ejecutamos mvn spring-boot:run

En nuestro caso podemos ver cómo la aplicación tarda unos 2 segundos en arrancar (dependiendo de la carga y demás)

En este post nos ocuparemos de usar el plugin de Maven con soporte para Buildpacks para generar un contenedor ligero que contendrá el ejecutable nativo GraalVM.

Para esto editaremos el pom.xml y añadiremos este plugin:

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

<configuration>

<image>

<builder>paketobuildpacks/builder:tiny</builder>

<env>

<BP_BOOT_NATIVE_IMAGE>true</BP_BOOT_NATIVE_IMAGE>

<BP_BOOT_NATIVE_IMAGE_BUILD_ARGUMENTS>

-Dspring.native.remove-yaml-support=true

-Dspring.spel.ignore=true

</BP_BOOT_NATIVE_IMAGE_BUILD_ARGUMENTS>

</env>

</image>

</configuration>

</plugin>

Estoy configurando este plugins con unos flags que reducen el footprint, además e usar el builder:tiny de los Paketo BuildPacks (en lugar del builder:base)

Luego añadiremos estos 2 repositorios:

<repositories>

<repository>

<id>spring-milestone</id>

<name>Spring milestone</name>

<url>https://repo.spring.io/milestone</url>

</repository>

</repositories>

y

<pluginRepositories>

<pluginRepository>

<id>spring-milestone</id>

<name>Spring milestone</name>

<url>https://repo.spring.io/milestone</url>

</pluginRepository>

</pluginRepositories>

Antes de lanzar la generación de la imagen que es un proceso costoso en recursos puede ser necesario incrementar la memoria asignada a Docker, en mi caso he pasado a 3 Gbs en lugar d ellos 3 Gbs por defecto.

Ahora ya estoy en disposición de generar la imagen con el comando:

mvn spring-boot:build-image

(si estoy ejecutando en Windows tendré que ejecutarlo desde una Shell tipo la de MINGW que trae el cliente de github):

El proceso de generación de la imagen es costoso y lento (en mi caso 14 minutos):

Una vez generada podré ejecutar el contenedor Docker de la aplicación Spring Boot:

docker run -p 8080:8080 docker.io/library/rest-service:0.0.1-SNAPSHOT

donde puedo ver que ahora el tiempo de arranque es prácticamente instantáneo (menos de 100 ms)

Respuestas

  1. Hola, me parece super interesante pero tengo problemas con el ejemplo al hacer la imagen, marca un error con DataSize.

    Encontre esto pero no arranca el proyecto.

    –initialize-at-build-time=org.springframework.util.unit.DataSize

  2. Otra cosa no puedes publicar comentarios. elimine un textarea que es oculto

    Form submission failed, as the element named » was implicitly closed by reaching the end of the file. Please add an explicit end tag (»)

Deja un comentario