Primeros pasos con Quarkus

supersonic

supersonic


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.

Estructura proyecto Quarkus con Maven | Primeros pasos con Quarkus
Estructura proyecto Quarkus con Maven

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


4 pensamientos sobre “Primeros pasos con Quarkus

  1. 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

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *