Desarrollando microservicios reactivos con Micronaut

Micronaut es un nuevo framework para la JVM que aguanta Java, Groovy y Kotlin y que está desarrollado para edificar microservicios cloud native.

La versión actual de Micronaut deja edificar un JAR con un Hello World que ocupa 10MB y que se puede ejecutar con un heap de tan solo 8MB siendo el tiempo de arranque de menos de un segundo cuando programamos con Java. Además de esto el tiempo de arranque de Micronaut y el consumo de memoria no medra linealmente con el número de líneas de código pues toda la inyección de dependencias, AOP y generación de proxies ocurre en tiempo de colección.

El proyecto ha sido creado por OCI y exactamente el mismo equipo que desarrolla el framework Grails. Fue oficialmente presentado por Graeme Rocher en Greach dos mil dieciocho el pasado Marzo en la capital española, liberado con licencia Apache dos.0 el veintitres de Mayo y publicada la primera version milestone el treinta de Mayo.

Entre los objetivos con los que se ha desarrollado Micronaut se encuentran:

Arranque prácticamente instantáneo
Bajísimo consumo de memoria
De forma fácil testeable
Inyección de dependencias y AOP
JAR generados de poquísimo tamaño
Prácticamente sin dependencies externas
doce factor
Micronaut da un servidor y cliente del servicio HTTP aparte de aguantar microservicios reactive y non-blocking al estar basado en Netty. En la una parte del usuario HTTP, es posible edificar uno declarativamente con una simple interfaz Java y anotaciones. Este usuario es incorporado, en contraste a la mayor parte de herramientas y bibliotecas existentes, en tiempo de compilatión, lo que hace que se reduzca el consumo de memoria.

Como no podía ser de otro modo, Micronaut asimismo aguanta GORM – el ORM de Grails – que da un conjunto de APIs para acceder de una forma fácil y potente a todo género de bases de datos SQL, como Neo4J, Redis, MongoDB, GraphQL y Cassandra.

Micronaut está desarrollado por los autores del framework Grails y se inspira en las lecciones aprendidas tras crear muchas aplicaciones, tanto monolitos como microservicios, a lo largo de los años usando Spring, Spring Boot y Grails.

Empecemos

Micronaut da un CLI para poder crear aplicaciones sencillamente. Para instalarlo usaremos SDKMan!, del que charlamos hace ya tiempo.

dólares americanos sdk install micronaut diez.0.M1

Una vez instalado el usuario podemos crear una aplicación ejecutando:

dólares americanos mn create-aplicación my-aplicación

Por defecto Micronaut crea una aplicación Java y usa Gradle como sistema de build mas es sencillísimo, por poner un ejemplo crear una aplicación Kotlin y utilizar Maven:

mn create-aplicación -build maven -features kotlin my-aplicación

Además de esto, si ejecutamos solamente mn vamos a entrar en el modo perfecto interactivo en el que tenemos autocompletado utilizando el tabulador y vamos a poder ver todas y cada una de las opciones y comando existentes:

mn
| Starting interactive mode…
| Entrar a command name to run. Use TAB for completion:
mn>

create-aplicación create-federation create-function create-profile help list-profiles profile-info

mn> create-aplicación –

-inplace -build -lang -profile -features

mn> list-profiles
| Available Profiles
——————–
* base – The base profile
* federation – The federation profile
* function – The function profile
* function-aws – The function profile for AWS Lambda
* service – The service profile

mn> profile-info base
Profile: base
——————–
The base profile

Provided Commands:
——————–
* create-bean – Creates a singleton bean
* create-job – Creates a job with scheduled method
* help – Prints help information for a specific command

Provided Features:
——————–
* annotation-api – Adds Java annotation API
* config-consul – Adds support for Distributed Configuration with Consul (https://www.consul.io)
* discovery-consul – Adds support for Service Discovery with Consul (https://www.consul.io)
* discovery-voilá – Adds support for Service Discovery with Voilá
* groovy – Creates a Groovy application
* hibernate-gorm – Adds support for GORM persistence framework
* hibernate-jpa – Adds support for Hibernate/JPA
* http-client – Adds support for creating HTTP clients
* http-server – Adds support for running a Netty server
* java – Creates a Java application
* jdbc-dbcp – Configures SQL DataSource instances using Commons DBCP
* jdbc-hikari – Configures SQL DataSource instances using Hikari Connection Pool
* jdbc-tomcat – Configures SQL DataSource instances using Tomcat Connection Pool
* junit – Adds support for the JUnit testing framework
* kotlin – Creates a Kotlin application
* mongo-gorm – Configures GORM for MongoDB for Groovy applications
* mongo-reactive – Adds support for the Mongo Reactive Streams Driver
* neo4j-bolt – Adds support for the Neo4j Bolt Driver
* neo4j-gorm – Configures GORM for Neo4j for Groovy applications
* redis-lettuce – Configures the Lettuce driver for Redis
* security-jwt – Adds support for JWT (JSON Web Token) based Authentication
* security-session – Adds support for Session based Authentication
* spek – Adds support for the Spek testing framewokr
* spock – Adds support for the Spock testing framework
* tracing-jaeger – Adds support for distributed tracing with Jaeger (https://www.jaegertracing.io)
* tracing-zipkin – Adds support for distributed tracing with Zipkin (https://zipkin.io)

Nuestro primer servicio

El próximo código muestra de qué manera crear un endpoint HTTP en Micronaut:

@Controller(/hello)
public class HelloController undefined

Como se puede ver el modelo de programación es muy afín a Spring Boot o bien Grails. Los desarrolladores que estén habituados a los dos frameworks tendrán una curva de aprendizaje bajísima. Esto dejará, por servirnos de un ejemplo una transición veloz y fácil a Micronaut.

Si arrancamos la aplicación y nos conectamos con un navegador (por defecto el servidor HTTP se ejecuta en un puerto azaroso mas es posible acotar uno por configuración) vamos a ver algo como esto:

dólares americanos ./gradlew run
> Task :run
23:59:44.420 [main] INFO io.micronaut.runtime.Micronaut – Start-up completed in 502ms. Server Running: http://localhost:43134

¿Y esto de qué forma lo testamos?

Para esto vamos a emplear Spock si bien es posible emplear JUnit o bien Spek si de esta forma lo queremos.

Primeramente crearemos una interfaz que nos dejará comunicarnos con el servidor. Micronaut va a ser el responsable de, en tiempo de colección, incorporar la interfaz con el cliente del servicio HTTP por nosotros.

@Client('/hello')
interfaz HelloClient undefined

Ya podemos crear el test:

class HelloControllerSpec extends Specification undefined

Creamos una instancia única y compartida por todos y cada uno de los tests de un servidor embebido que ejecuta nuestra aplicación.
Conseguimos el bean de la interfaz HelloClient que hemos definido previamente y que utilizaremos como cliente del servicio HTTP para conectarnos al servidor. Recordemos que Micronaut ha incorporado el usuario HTTP.
Ejecutamos la llamada HTTP y verificamos el resultado.
Una de las premisas con las que se ha construido Micronaut es que sea rapidísimo y fácil de probar. Cuando usamos frameworks como Spring y Grails, escribimos primordialmente test unitarios en vez de tests funcionales o bien de integración no pues prefiramos hacerlo ni por el hecho de que sea deseable, sino más bien por el hecho de que los tests funcionales son lentísimos. Tendemos a mockear nuestra infraestructura, dependencias,… sencillamente pues arrancar el servidor es lento y pesado. En Micronaut todo ocurre en tiempo de colección conque la velocidad de ejecución de los tests es rapidísima.

Como podemos ver la ejecución del test es de solo ciento ochenta y cinco ms. Esto no es ningún truco. Es la aplicación real comunicandose usando HTTP con el servidor. Para revisarlo podemos acrecentar el nivel del log del cliente del servicio HTTP agregando al fichero logback.xml:

Si ejecutamos el test nuevamente podemos revisar que se hacen solicitudes HTTP reales entre el usuario y el servidor.

Programación reactiva

Micronaut asimismo aguanta programación reactiva out-of-the-box al incorporar Reactive Streams con lo que es posible usar cualquier biblioteca que lo soporte como RxJava2, Reactor o bien Akka.

Vamos a incorporar soporte RxJava2 al ejemplo anterior:

@Get(/undefined)
public Single hello(String name) undefined

En vez de devolver un String devolvemos un Single. La clase Single de RxJava2 incorpora el Patrón Reactivo para un solo valor de contestación.
Creamos un Single desde el mensaje con la contestación.
El usuario quedaría:

@Client('/hello')
interfaz HelloClient undefined

Y por último el test:

void test hello world() undefined

En el test transformamos la llamada en bloqueante
Con un pequeño cambio tenemos una implementación reactive y non-blocking en el servidor y un cliente del servicio reactive para testar todo.

Micronaut es más que esto

Hemos visto un caso sencillísimo mas Micronaut ofrece gran cantidad de opciones y peculiaridades pensadas en Microservicios:

Service discovery: Con soporte de Consul y Voilá
Circuit Breaker con soporte de Retry
Configuración compartida
Usuario HTTP con Cargar-Balancing
Tracing con soporte para Zipkin y Jaeger
Seguridad
Soporte de serverless en AWS Lambda
Soporte para Hystrix y Ribbon
Micrometer
Y considerablemente más integraciones
Otra característica a resaltar es que estas integraciones están construidas sin incorporar práctiacemente dependencias auxiliares al framework lo que evita que los JARs finales tenga excesivo tamaño.

Más información

Esto es solo el inicio. Podeis hallar el código completo de la apliación hello-world en Github.

Para conocer más sobre el framework aconsejo la de presentación de Graeme: Launching the Micro Future: Groovy, Grails and Project Particle libre en el canal de Youtube de Greach.

Asimismo está libre la documentación oficial, la documentación del API y guías con diferentes ejemplos dónde se van a ir agregando nuevas en los próximos meses.

Por último la versión Milestone dos va a estar libre a final de Junio y se espera la versión final diez ya antes de final de año.