Site icon Blog Zenika

Développer une application Cloud Ready avec Quarkus

Il y a quelques mois déjà, je vous avais parlé de Quarkus, le nouveau framework de développement de microservices en Java, pensé pour le cloud et les containers. Si vous n’aviez pas lu l’article à cet époque, et voulez découvrir ce framework, c’est ici : Zoom sur Quarkus.

Depuis, Quarkus est sorti en version 1.0 et j’ai eu la chance d’en parler au Devfest Nantes et plus particulièrement de comment Quarkus répond aux problématiques du Cloud. 

C’est le sujet de cet article : le développement d’application Cloud Ready avec Quarkus.

Cloud Ready

Difficile de donner une définition à ce qu’est une application Cloud Ready.

Beaucoup de gens citent les principes des 12 Factors applications https://12factor.net/

Ils définissent certains principes qui dépassent le cadre des applications Cloud Ready mais on peut noter les principes suivants :

Pour définir ce qu’est une application, on peut aussi citer les principes définis dans le livre blanc Container native applications de RedHat : https://www.redhat.com/en/resources/cloud-native-container-design-whitepaper

Ce livre blanc se concentre sur les applications à déployer dans des containers, et c’est généralement ce que l’on déploie dans le Cloud.

Ce livre blance reprend certains principes des 12 factors applications et insiste sur certains points essentiels pour le déploiement via conteneurs :


La réponse de Quarkus

Container native

Quarkus est un framework qu’on pourrait qualifier de Container Native. Il a été pensé dès le début pour être déployé dans un conteneur.

À l’initialisation d’un projet Quarkus, des Dockerfile par défaut sont fournis, et la documentation explique comment les utiliser pour déployer dans Kubernetes (qui est un des standards d’orchestration de conteneur) ou OpenShift.

Par défaut, le packaging d’une application Quarkus produit un JAR avec les classes de vos applications, et un répertoire lib avec toutes vos librairies. En copiant les librairies dans votre conteneur Docker via un layer séparé du JAR de votre application, vous évitez de changer ce layer à chaque packaging de votre application, ce qui améliore nettement le temps de création de votre conteneur ainsi que sa taille.

Un framework d’extension

Quarkus est un framework d’extension, le coeur de Quarkus est très petit. Quarkus apporte principalement ses fonctionnalités via l’intégration de librairies existantes via une extension.

Une extension permet d’intégrer une librairie dans Quarkus pour qu’elle :

Chaque extension va importer uniquement les librairies nécessaires à son fonctionnement. 

Quarkus sépare le déploiement (build) du runtime : si une librairie n’est nécessaire qu’au build (par exemple une librairie pour lire un fichier de configuration XML), elle ne sera pas chargée au runtime (ni packagée), ce qui économise de la mémoire et de l’espace disque.

Chaque extension va pouvoir exécuter des étapes de build (build steps) qui seront exécutées via le plugin Maven/Gradle et permettre une optimisation du temps de démarrage et de l’empreinte mémoire, en déplaçant des étapes de démarrage de la librairie au build au lieu du runtime (par exemple : l’analyse d’annotations).

Quarkus minimise l’utilisation de la réflexion à l’exécution en utilisant de la génération de bytecode au build time. Ça permet encore un démarrage plus rapide de votre application.

Tout ça est un peu compliqué, mais c’est une des forces de Quarkus. 

Pour plus d’information : https://quarkus.io/guides/writing-extensions

GraalVM

Pour faire simple, GraalVM est un projet mené par Oracle Labs dans le but d’implémenter une machine virtuelle Java en Java, et de pouvoir exécuter via celle-ci n’importe quel langage de programmation de manière interopérable (on peut appeler une méthode d’un langage depuis un autre).

GraalVM se base sur la machine virtuelle HotSpot (celle d’OpenJDK) et contient un ensemble de composants que voici.

Quarkus s’intègre avec deux composants spécifiques :

SubstrateVM vient avec quelques limitations :

Quarkus s’intègre avec GraalVM en faisant en sorte que toutes les extensions soient compatibles. Il facilite aussi l’utilisation de l’outil native-image en l’appelant pour nous via son plugin Maven.
Plus d’informations : https://quarkus.io/guides/writing-native-applications-tips.


Les fonctionnalités Cloud ready de Quarkus :

Quarkus propose de nombreuses fonctionnalités Cloud Ready, principalement basées sur Eclipse Microprofile et SmallRye une de ses implémentations.

Documentation d’API

OpenAPI permet de documenter vos API avec un jeu d’annotations défini dans la spécification OpenAPI v3 (inspiré de Swagger) : @OpenAPIDefinition, @Operation, @APIResponse, @Parameter, …

Pour les utiliser, il faut ajouter l’extension smallrye-openapi dans votre pom.xml :

<dependency>
 <groupId>io.quarkus</groupId>
 <artifactId>quarkus-smallrye-openapi</artifactId>
</dependency>

Puis ajouter les annotations nécessaires à votre ressource JAX-RS :

@Path("/bookmarks")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@OpenAPIDefinition(info = @Info(title = "The Bookmark API", version = "1.0"))
public class BookmarkResource {

   @GET
   @Operation(summary = "List all bookmarks")
   public List<Bookmark> listAll() {
       return Bookmark.listAll();
   }

   @GET
   @Path("/{id}")
   @Operation(summary = "Get a bookmark")
   public Bookmark get(@PathParam("id") @Parameter(description = "Bookmark identifier") Long id) {
       return Bookmark.findById(id);
   }

}

Vous aurez ensuite accès à la documentation au format OpenAPI v3 via http://localhost:8080/openapi
En mode dev (configurable), un swagger UI est déployé pour pouvoir directement visualiser cette documentation et tester votre application via http://localhost:8080/swagger-ui

Heath Check

Quakus propose un système de Heath Check (littéralement test de vie de votre application) via Microprofile Health.

Pour les utiliser, il faut ajouter l’extension smallrye-health à votre pom.xml :

<dependency>
 <groupId>io.quarkus</groupId>
 <artifactId>quarkus-smallrye-health</artifactId>
</dependency>

Vous pouvez ensuite utiliser l’URL http://localhost:8080/health pour récupérer l’état de santé de votre application.

Les health checks sont séparés en readiness et liveness checks, ceci permet une intégration facilité avec Kubernetes qui sépare les deux notions :

Par défaut, certaines extensions fournissent des Readiness Check automatiquement (par exemple Agroal pour les checks de base de données).

Si vous nécessitez d’autres checks, vous pouvez les développer vous-même en suivant ce guide : https://quarkus.io/guides/health-guide

Voici un exemple de Health Check custom :

@Readiness
public class MyHealCheck implements HealthCheck {

   @Override
   public HealthCheckResponse call() {
       return HealthCheckResponse.builder().name("custom").withData("key", "value").up().build();
   }
}

Metrics

Quarkus fournit de la métrologie compatible Prometheus via Microprofile Metrics.

Pour l’utiliser il faut ajouter l’extension smallrye-metrics :

<dependency>
 <groupId>io.quarkus</groupId>
 <artifactId>quarkus-smallrye-metrics</artifactId>
</dependency>

Vous aurez ensuite un ensemble de métriques systèmes par défaut accessible via : http://localhost:8080/metrics

Certaines extensions fournissent des métriques, désactivées par défaut (car le coût de la récupération des métriques peut être important). C’est le cas d’Agroal par exemple, qui publie les métriques du pool de connection.

Si vous voulez ajouter vos propres métriques, vous pouvez le faire facilement via les annotations @Counted, @Timed and @Gauge.

Plus d’information dans le guide sur les métriques:  : https://quarkus.io/guides/opentracing-guide 

Voici un exemple de métrique sur un endpoint JAX-RS:

@Path("/bookmarks")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class BookmarkResource {

   @GET
   @Counted(name = "listAll.count")
   @Timed(name="listAll.time")
   public List<Bookmark> listAll(){
       return Bookmark.listAll();
   }

   @GET
   @Path("/{id}")
   @Counted(name = "get.count")
   @Timed(name="get.time")
   public Bookmark get(@PathParam("id") Long id) {
       return Bookmark.findById(id);
   }
}

Tracing

Quarkus fournit une implémentation de métrique compatible OpenTracing via Microprofile Tracing et implémentée par Jaeger.

Pour l’utiliser il faut ajouter l’extension smallrye-opentracing :

<dependency>
 <groupId>io.quarkus</groupId>
 <artifactId>quarkus-smallrye-opentracing</artifactId>
</dependency>
<dependency>
 <groupId>io.opentracing.contrib</groupId>
 <artifactId>opentracing-jdbc</artifactId>
</dependency>

J’ai aussi intégré ici la librairie optionnelle opentracing-jdbc qui permet d’activer le tracing des requêtes SQL.

Pour finir, il faut configurer l’extension Jaeger :

quarkus.jaeger.service-name=prepaid-card-api
quarkus.jaeger.sampler-type=const
quarkus.jaeger.sampler-param=1
quarkus.jaeger.endpoint=http://localhost:14268/api/traces

Ici on va utiliser un sample de type constant et tracer tous les appels (sampler-param=1).

Il n’y a aucun code spécifique pour activer le tracing. 

Plus d’information dans le guide Open Tracing.

Fault Tolerance

Dans le Cloud, tout peut arriver, chaque composant peut planter !

Pour palier à ça, il est fréquent d’utiliser des techniques de fault tolerance (littéralement tolérance à la panne) telle que des retry (rejeux), fallback (traitement par défaut), circuit breaker, …

Pour cela, Quarkus fournit une implémentation de Microprofile Fault Tolerance qui fournit les annotations @Retry, @Timeout, @Fallback, @CircuitBreaker and @BulkHead.

Pour l’utiliser, il faut ajouter l’extension smallrye-fault-tolerance :

<dependency>
 <groupId>io.quarkus</groupId>
 <artifactId>quarkus-smallrye-fault-tolerance</artifactId>
</dependency>

Plus d’information dans le Guide Fault Tolerance.

Configuration 

Quarkus propose un système de configuration centralisé dans un fichier application.properties ou application.yaml.

Chaque propriété de configuration est surchargeable via variable d’environnement ou propriété système Java (via -D).

On peut externaliser ce fichier de configuration sur le disque dur si nécessaire. Mais dans un environnement Cloud Ready, pour coller aux principes édictés ci-dessus, on privilégie les variables d’environnement comme surchage des valeurs de configuration.

Toutes les extensions Quarkus utilisent ce système de configuration centralisé.

Pour l’utiliser au sein de notre application, il faut utiliser l’annotation @ConfigProperty pour injecter une propriété du fichier de configuration dans notre application.

Par exemple si vous avez la propriété suivante dans votre fichier de configuration :

 greeting=World

Vous pouvez l’injecter via la ligne de code suivante :

@ConfigProperty(name="greeting") String greeting;

Quarkus permet aussi de gérer des profils de configuration pour définir des valeurs différentes pour différents environnements au sein du même fichier de configuration.

Quarkus vient avec trois profils par défaut:

On peut définir ses propres profils qui peuvent être sélectionnés via la variable d’environnement QUARKUS_PROFILE ou la propriété système quarkus.profile.

Quarkus propose aussi une intégration avec certains systèmes de configuration centralisés (dont Vault) ainsi que les ConfigMap et Secret Kubernetes. 

Plus d’information dans le guide sur la configuration.

Cloud native

Pour finir, Quarkus propose un ensemble d’extension Cloud Native, pour interagir avec les principaux Cloud public et Kubernetes.


Conclusion

Quarkus est depuis sa création un framework pensé pour les conteneurs et le déploiement vers le Cloud (et tout particulièrement Kubernetes). Il facilite grandement le déploiement de votre application comme un exécutable natif via son intégration poussée de GraalVM.

Via ses extensions Microprofile, vous aurez tout ce qu’il faut pour ajouter toutes les fonctionnalités Cloud Ready nécessaires à votre application. 

Et si vous voulez aller vers le Cloud natif, vous pouvez vous interfacer facilement avec les principaux Cloud Natif, et bien sûr, Kubernetes !
Pour aller plus loin, vous pouvez essayer de suivre le Dojo bookmarkit que j’ai développé pour mettre en pratique les fonctionnalités Cloud Ready de Quarkus.
Et si vous voulez directement la solution, elle est ici 😉


Le petit + :
La formation Développement d’applications Cloud Ready avec Quarkus


Auteur/Autrice

Quitter la version mobile