Primeros pasos con Quarkus
Actualmente, se ha hecho imprescindible que los desarrollos que se hacen se desplieguen en cualquier cloud sin importar la infraestructura, en donde los entornos en los que se ejecutan, las instancias que se crean y se destruyen y los tiempos de arranque de aplicación son sumamente importantes. Ante este panorama, apareció Quarkus un proyecto de RedHat, para poder llevar Java al Cloud de una manera mucho más eficiente. En este artículo contaremos los Primeros pasos con Quarkus, en el que veremos algunas de sus características.
Introducción
Java fue creado hace ya algo más de 20 años, y sigue todavía siendo uno de los lenguajes predominantes. Pero hoy en día, se tiende a ir a un mundo dominado por el cloud, contenedores, microservicios, FaaS (Function as a Service), etc. Por lo que aplicaciones cloud native van tomando cada vez más impulso.
Las aplicaciones cloud native pueden desarrollarse y aumentar la productividad y eficiencia, por lo que en entornos orientados al cloud Quarkus y Supersonic Subatomic Java, coge una importancia considerable.
Quarkus es un framework de Java nativo para Kubernetes que funciona bajo GraalVM y HotSpot, cuyo objetivo es hacer de java un lenguaje líder en kubernetes y entornos sin servidor y ofrecer a los desarrolladores un entorno de desarrollo reactivo e imperativo.
Manos a la obra en Quarkus
Creando el proyecto
La mejor y más práctica manera de crear nuestra primera aplicación es haciendo uso de maven, tendrás que tener al menos la versión 3.6.2 (mvn -version)
mvn io.quarkus:quarkus-maven-plugin:1.8.0.Final:create \ -DprojectGroupId=com.refactorizando.quarkus \ -DprojectArtifactId=quarkus-project \ -DclassName="com.refactorizando.quarkus.HelloWorldResource" \ -Dpath="/helloworld"
El comando de arriba generará la estructura básica del proyecto, con un endpoint helloworld y el Dockerfile necesario.
Analizando la estructura
El proyecto generado a través de maven, tiene la estructura típica que se usaría con cualquier otro framework. Las únicas excepciones serían la carpeta docker y el fichero index.html que se ha generado dentro de la carpeta resources.
Como hemos comentado anteriormente, la idea es facilitar el desarrollo para que pueda ser un framework nativo para Kubernetes, por eso en la carpeta docker, vamos a encontrar dos diferentes ficheros para jvm y para nativo.
Si analizamos nuestro fichero pom.xml podremos ver como se ha generado nuestro BOM de QuarKus, y el quarkus-maven-plugin, que será el responsable de empaquetar la aplicación y también nos proporcionará el modo desarrollo.
Inyección de dependencias en Quarkus
Al igual que muchos otros frameworks, Quarkus trae una solución de Inyección de Dependencias. Esta solución esta basada en ArC la cual es una inyección de dependencias basada en CDI (Contexts and Dependency Injection) para la arquitectura de Quarkus.
Para poder crear un bean vamos a hacer uso de la anotación @ApplicationScoped, cuyo funcionamiento sería el mismo que hace Spring con la anotación @Component. Una vez hemos creado ese bean, vamos a injectarlo en una clase, en este caso podremos hacer una inyección por constructor o haciendo uso de la anotación @Inject.
A continuación mostramos como se realizará la inyección de dependencias en Quarkus:
package com.refactorizando.quarkus; import javax.enterprise.context.ApplicationScoped; @ApplicationScoped public class HelloWorldService { public String sayHello(String name) { return "hello " + name; } }
package com.refactorizando.quarkus; import javax.inject.Inject; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import org.jboss.resteasy.annotations.jaxrs.PathParam; @Path("/helloworld") public class HelloWorldResource { @Inject HelloWorldService helloWorldService; @GET @Produces(MediaType.TEXT_PLAIN) @Path("/sayHello/{name}") public String hello(@PathParam String name) { return helloWorldService.sayHello(name); } @GET @Produces(MediaType.TEXT_PLAIN) public String hello() { return "hello"; } }
Recarga en caliente
Uno de las ventajas que trae Quarkus de serie es la recarga en caliente, es decir, cualquier modificación sobre el código será automáticamente aplicada, aunque esta funcionalidad únicamente estará disponible en el modo desarrollo (compile quarkus:dev).
Tomando como base la clase que hemos creado anteriormente HelloService y la modificación en la clase HelloWorldResource , vamos a realizar una modificación en el código y ver como se aplica «en caliente».
Ejecutamos:
mvn compile quarkus:dev
Creando una imagen de nuestro proyecto en Quarkus
Ahora vamos a ir con lo realmente atractivo de Quarkus, crear una imagen nativa. Esta imagen contendrá todo lo necesario para poder ser desplegada, tan solo vamos a tener que tener instalado GraalVM, al igual que tenemos instalado Java en nuestra Home y en nuestro IDE.
Recuerda tener instalado y configurado GraalVM
Ejecutamos el siguiente comando, para crear la imagen:
mvn package -Pnative
El comando anterior creará la imagen haciendo un pulling de quarkus/ubi-quarkus-native-image para crear un ejecutable nativo. A continuación, una vez finalizada la creación de la imagen, vamos a crear un ejecutable que correrá en el contenedor:
mvn package -Pnative -Dnative-image.docker-build=true
Y finalmente vamos a crear y a ejecutar la imágen creada con el arquetipo del proyecto y nuestra pequeña modificación añadida con la clase HelloWorldService.
docker build -f src/main/docker/Dockerfile.native -t quarkus/quarkus-project .
docker run -i --rm -p 8080:8080 quarkus/quarkus-project
Echa un ojo a lo que ha tardado en arrancar, el tiempo ha sido prácticamente 0.
Una de los aportes de Quarkus es su bajo tiempo de arranque
Desde tu navegador, postman o con curl ejecuta: http://localhost:8080/helloworld
Desplegando una aplicación Quarkus en Kubernetes
Para poder desplegar una aplicación Quarkus en Kubernetes, vamos a hacer uso de una serie de extensiones cuando utilicemos el arquetipo de maven para generar nuestro proyecto:
mvn io.quarkus:quarkus-maven-plugin:1.8.1.Final:create \ -DprojectGroupId=com.refactorizando.quarkus \ -DprojectArtifactId=quarkus-project \ -DclassName="com.refactorizando.quarkus.HelloWorldResource" \ -Dpath="/helloworld" -Dextensions="kubernetes, jib"
o para no tener que modificar el código anterior se podría añadir directamente las dependencias maven en nuestro pom.xml:
<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-kubernetes</artifactId> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-container-image-jib</artifactId> </dependency>
Estas dependencias van a crear los json/yaml de los servicios y los deployment :
--- apiVersion: v1 kind: ServiceAccount metadata: annotations: app.quarkus.io/build-timestamp: 2020-09-02 - 18:42:35 +0000 labels: app.kubernetes.io/name: quarkus-project app.kubernetes.io/version: 1.0-SNAPSHOT name: quarkus-project --- apiVersion: v1 kind: Service metadata: annotations: app.quarkus.io/build-timestamp: 2020-09-02 - 18:42:35 +0000 labels: app.kubernetes.io/name: quarkus-project app.kubernetes.io/version: 1.0-SNAPSHOT name: quarkus-project spec: ports: - name: http port: 8080 targetPort: 8080 selector: app.kubernetes.io/name: quarkus-project app.kubernetes.io/version: 1.0-SNAPSHOT type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: annotations: app.quarkus.io/build-timestamp: 2020-09-02 - 18:42:35 +0000 labels: app.kubernetes.io/name: quarkus-project app.kubernetes.io/version: 1.0-SNAPSHOT name: quarkus-project spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: quarkus-project app.kubernetes.io/version: 1.0-SNAPSHOT template: metadata: annotations: app.quarkus.io/build-timestamp: 2020-09-02 - 18:42:35 +0000 labels: app.kubernetes.io/name: quarkus-project app.kubernetes.io/version: 1.0-SNAPSHOT spec: containers: - env: - name: KUBERNETES_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: nrodriguez/quarkus-project:1.0-SNAPSHOT imagePullPolicy: IfNotPresent name: quarkus-project ports: - containerPort: 8080 name: http protocol: TCP serviceAccount: quarkus-project
A continuación aplicamos estos ficheros haciendo uso del comando kubectl:
kubectl apply -f target/kubernetes/kubernetes.yaml
Conclusión en primeros pasos con Quarkus
En estos primeros pasos con Quarkus hemos visto como podemos crear un helloworld hasta su despliegue en kubernetes, haciendo uso básicamente de las características que nos aporta Quarkus. Además hemos podido ver como los tiempos de arranque son bastante rápido comparado con otros frameworks.
Otros artículos que te pueden interesar
Ejemplo de aplicación de Spring Boot y Kubernetes
Ejercicios de Labels y Selectors en Kubernetes
Usando el ServiceAccount en Kubernetes
excelente!, un manual bastante preciso para ver las bondades que ofrece esta tecnología, sorprende tambien lo rapido que es quarkus desplegado, incluído los cambios en caliente en la misma imagen