Micronaut es un framework para microservicios en la JVM que no utiliza reflection y pre-calcula todo lo necesario para el funcionamiento de las aplicaciones ahead-of-time (AoT) durante la compilación. De esta forma consigue que las aplicaciones arranquen extremadamente rápido y que consuman muy poca memoria.
¿Qué pasaría si te dijera que puedes reducir el tiempo de arranque en órdenes de magnitud? ¿Y si pudieras reducir aún más el consumo de memoria?
GraalVM es una nueva máquina virtual de Oracle que soporta muchos lenguajes en runtime. Además GraalVM tiene la habilidad de compilar las aplicaciones Java a binarios nativos, haciendo que sea el compañero ideal de Micronaut. En esta charla aprenderás cómo funciona GraalVM y cómo puedes aprovechar toda su potencia para convertir tus aplicaciones Micronaut a binarios nativos.
6. Iván López @ilopmar
Limitaciones
- Dynamic class loading (no soportado)
- Reflection (con configuración)
- Dynamic proxy (con configuración)
- Unsafe Memory Access (parcialmente)
- Class initializers (soportado)
- InvokeDynamic bytecode y method handlers (parcialmente)
- Lambda (soportado)
- Finalizers (no soportado)
- Threads (soportado)
7.
8. Iván López @ilopmar
Micronaut
- Framework para microservicios en la JVM
- Ultra-ligero & reactive (basado en Netty)
- Java, Groovy & Kotlin
- Ahead of Time compilation (AoT)
- Sin reflection ni runtime proxies
- Arranque muy rápido
- Consumo de memoria bajo
- Natively Cloud Native
- Micronaut Data
- Soporte para GraalVM
9. Iván López @ilopmar
Crear aplicación con soporte para GraalVM
$ mn create-app basic-app
--features=graal-native-image
10. Iván López @ilopmar
Soporte en Micronaut para GraalVM
- Dependencias
- Dockerfile
compileOnly "com.oracle.substratevm:svm"
annotationProcessor "io.micronaut:micronaut-graal"
FROM oracle/graalvm-ce:19.2.1 as graalvm
COPY . /home/app/basic-app
WORKDIR /home/app/basic-app
RUN native-image --no-server -cp build/libs/basic-app-*-all.jar
FROM frolvlad/alpine-glibc
EXPOSE 8080
COPY --from=graalvm /opt/graalvm-ce-19.2.1/jre/lib/amd64/libsunec.so
/app/libsunec.so
COPY --from=graalvm /home/app/basic-app/basic-app /app/basic-app
ENTRYPOINT ["/app/basic-app", "-Djava.library.path=/app"]
11. Iván López @ilopmar
Soporte en Micronaut para GraalVM (II)
- native-image.properties
Args = -H:IncludeResources=logback.xml|application.yml|bootstrap.yml
-H:Name=basic-app
-H:Class=example.micronaut.Application
16. Iván López @ilopmar
Depurar errores
[basic-app:15340] classlist: 14,103.05 ms
[basic-app:15340] (cap): 3,947.49 ms
[basic-app:15340] setup: 6,654.60 ms
[basic-app:15340] analysis: 68,716.43 ms
Error: No instances of io.netty.buffer.PooledByteBufAllocator are allowed in the image heap as this
class should be initialized at image runtime. Object has been initialized by the
io.micronaut.buffer.netty.NettyByteBufferFactory class initializer with a trace:
at io.netty.buffer.PooledByteBufAllocator.<init>(PooledByteBufAllocator.java:187)
at io.netty.buffer.PooledByteBufAllocator.<clinit>(PooledByteBufAllocator.java:168)
at io.netty.buffer.ByteBufUtil.<clinit>(ByteBufUtil.java:84)
at io.netty.buffer.ByteBufAllocator.<clinit>(ByteBufAllocator.java:24)
at io.micronaut.buffer.netty.NettyByteBufferFactory.<init>(NettyByteBufferFactory.java:62)
at io.micronaut.buffer.netty.NettyByteBufferFactory.<clinit>(NettyByteBufferFactory.java:44)
. To fix the issue mark io.netty.buffer.PooledByteBufAllocator for build-time initialization with
--initialize-at-build-time=io.netty.buffer.PooledByteBufAllocator or use the the information from
the trace to find the culprit and --initialize-at-run-time=<culprit> to prevent its instantiation.
. To fix the issue mark io.netty.buffer.PooledByteBufAllocator for build-time initialization with
--initialize-at-build-time=io.netty.buffer.PooledByteBufAllocator or use the the information from
the trace to find the culprit and --initialize-at-run-time=<culprit> to prevent its instantiation.
17. Iván López @ilopmar
Depurar errores
Detailed message:
Trace: object io.micronaut.buffer.netty.NettyByteBufferFactory
object io.micronaut.buffer.netty.NettyByteBufferFactory$$Lambda$95116b6497efb4cbd0dc7c4dc91186562d629e7b
object io.micronaut.core.convert.TypeConverter$$Lambda$802fd3b66b18a7bf114f797df2507ad969fcb1c0
object java.util.concurrent.ConcurrentHashMap$Node
object java.util.concurrent.ConcurrentHashMap$Node[]
object java.util.concurrent.ConcurrentHashMap
object io.micronaut.core.convert.DefaultConversionService
method io.micronaut.http.server.netty.NettyHttpResponseFactory.status(HttpStatus, String)
Call path from entry point to io.micronaut.http.server.netty.NettyHttpResponseFactory.status(HttpStatus, String):
at io.micronaut.http.server.netty.NettyHttpResponseFactory.status(NettyHttpResponseFactory.java:61)
at io.micronaut.http.HttpResponseFactory.status(HttpResponseFactory.java:74)
at io.micronaut.http.HttpResponse.serverError(HttpResponse.java:189)
at
io.micronaut.http.server.netty.RoutingInBoundHandler.lambda$exceptionCaughtInternal$3(RoutingInBoundHandler.java:403)
at io.micronaut.http.server.netty.RoutingInBoundHandler$$Lambda$1102/974221323.call(Unknown Source)
at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:140)
at java.lang.Thread.run(Thread.java:748)
at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:460)
at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:193)
at com.oracle.svm.core.code.IsolateEnterStub.PosixJavaThreads_pthreadStartRoutine_e1f4a8c0039f8
Error: Use -H:+ReportExceptionStackTraces to print stacktrace of underlying exception
Error: Image build request failed with exit status 1
21. Iván López @ilopmar
Y esto… ¿cómo se testea?
- Crear una imagen nativa tarda mucho
- Y necesita mucha RAM
- GraalVM cambia muy rápido (y a veces rompen cosas)...
- ...y nosotros también ;-)
- Usamos Travis para Micronaut, pero...
- ...Travis tiene límite para la RAM
- Necesitábamos otra opción.
22.
23. Iván López @ilopmar
Tests usando Gitlab CI
- Job periódico cada hora
- Sólo si nuevos commit en Micronaut o Graal
- Compila Graal desde el código fuente
- Crea imágenes nativas de aplicaciones de prueba de Micronaut
- Ejecuta tests funcionales
- https://github.com/micronaut-graal-tests
- https://gitlab.com/micronaut-projects/micronaut-graal-tests
24. Iván López @ilopmar
Aplicaciones de prueba Micronaut-GraalVM
- Basic application: DI, serialización de POJO, tipos reactivos
- Micronaut function: AWS Function
- Service discovery: Soporte Consul & HTTP Client
- Static resources & views: Handlebars, Thymeleaf, Freemarker y Velocity
- Endpoints de Management & Metrics
- Distributed tracing: Zipkin
- RabbitMQ: Fire-and-forget & RPC
- Security con JWT
- Micronaut Data: H2, Postgresql, Oracle
34. Iván López @ilopmar
Resumen
GraalVM es una tecnología
nueva e interesante
Cuidado con las
limitaciones y casos de
uso
Soporte out-of-the-box
en Micronaut
Mejoras en cada release Arranque más rápido &
menos consumo de
memoria
Desarrolladores
contentos y productivos
35. SLIDE TITLE 27 PT ALL CAPS
¡Gracias!
@ilopmar
lopez.ivan@gmail.com
https://github.com/ilopmar
Iván López
http://bit.ly/commit-mn-graal
¿Preguntas?