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, cómo sacar provecho a GraalVM en tus aplicaciones Micronaut convirtiéndolas a aplicaciones nativas y cómo funciona la integración de ambos frameworks.
9. 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 (mejorado en Micronaut 2.0)
10. Iván López @ilopmar
Crear aplicación con soporte para GraalVM
$ mn create-app basic-app
--features=graalvm
11. Iván López @ilopmar
Soporte en Micronaut para GraalVM
- Dependencias
- Dockerfile
compileOnly "org.graalvm.nativeimage:svm"
annotationProcessor "io.micronaut:micronaut-graal"
FROM oracle/graalvm-ce:20.1.0-java8 as graalvm
RUN gu install native-image
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
RUN apk update && apk add libstdc++
EXPOSE 8080
COPY --from=graalvm /home/app/basic-app/basic-app /app/basic-app
ENTRYPOINT ["/app/basic-app"]
12. Iván López @ilopmar
Soporte en Micronaut para GraalVM (II)
- native-image.properties
Args = -H:Name=basic-app
-H:Class=example.micronaut.Application
16. Iván López @ilopmar
Micronaut incluye todo lo necesario (II)
@AutomaticFeature
final class HibernateFeature implements Feature {
@Override
public void beforeAnalysis(BeforeAnalysisAccess access) {
// other drivers...
registerIfPresent(access, "oracle.jdbc.OracleDriver",
Oracle8iDialect.class,
Oracle9iDialect.class,
Oracle10gDialect.class,
Oracle12cDialect.class);
}
}
21. 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.
22. 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
27. 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 ;-)
- Usabamos Travis para Micronaut (ahora Github Actions), pero...
- ...Travis tiene límite para la RAM
- Necesitábamos otra opción.
28.
29. Iván López @ilopmar
Tests usando Gitlab CI
- Jobs periódicos cada hora (master / 1.3.x)
- Sólo si nuevos commit en Micronaut o GraalVM
- Compila GraalVM desde el código fuente (JDK8 & JDK 11)
- 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
30. Iván López @ilopmar
Aplicaciones de prueba Micronaut-GraalVM
- Basic application: DI, serialización de POJO, tipos reactivos, HTTP Client
- Cache
- Micronaut function
- Service discovery: Consul & Eureka
- Static resources & views: Handlebars, Thymeleaf, Freemarker y Velocity
- Endpoints de Management & Metrics
- Distributed tracing: Zipkin
- RabbitMQ: Fire-and-forget & RPC
31. Iván López @ilopmar
Aplicaciones de prueba Micronaut-GraalVM
- Security: JWT, Basic Auth, Cookie, Session
- Scheduled jobs
- Micronaut Data JDBC: H2, Postgresql, Oracle, MariaDB, MS SQL Server
- Micronaut Data JPA-Hibernate: H2, Postgresql, MariaDB
- Bean Introspection
- Servlet: Tomcat & Jetty
- Flyway
45. Iván López @ilopmar
Casos de uso
- https://launch.micronaut.io (Google Cloud Functions)
- Micronaut CLI: Linux, MacOS, Windows
- AWS Lambda + Custom runtime
- Azure Functions
46. 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
47. SLIDE TITLE 27 PT ALL CAPS
¡Gracias!
@ilopmar
lopez.ivan@gmail.com
https://github.com/ilopmar
Iván López
https://bit.ly/bcn-jug-micronaut
¿Preguntas?