Blog ENI : Toute la veille numérique !
🐠 -25€ dès 75€ 
+ 7 jours d'accès à la Bibliothèque Numérique ENI. Cliquez ici
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. Quarkus
  3. Développement d’applications réactives
Extrait - Quarkus Développer des applications microservices en Java pour le cloud et Kubernetes
Extraits du livre
Quarkus Développer des applications microservices en Java pour le cloud et Kubernetes Revenir à la page d'achat du livre

Développement d’applications réactives

Architecture réactive et application réactive

On parle de réactif pour définir un ensemble de principes et de bonnes pratiques dans la construction de systèmes et d’applications distribués et réactifs.

Le manifeste réactif définit les systèmes réactifs comme des systèmes distribués présentant quatre caractéristiques :

  • Réactivité : ils doivent répondre en temps voulu.

  • Élasticité : ils s’adaptent aux fluctuations de la charge.

  • Résistance : ils gèrent les défaillances avec élégance.

  • Via messages asynchrones : les composants d’un système réactif interagissent à l’aide de messages.

On parle d’une architecture réactive ou d’un système réactif quand les composants qui le constituent utilisent des messages asynchrones pour communiquer entre eux. Grâce à l’utilisation de messages asynchrones à la place d’appels synchrones, les composants ne dépendent pas les uns des autres. Des erreurs dans un composant n’empêchent pas un autre composant de lui envoyer un message, et la consommation d’un message se fait à la vitesse du consommateur, évitant tout risque de surcharge ou d’erreur en cascade. L’élasticité permet...

Vert.x : le cœur réactif de Quarkus

Eclipse Vert.x est un toolkit (boîte à outils en français) pour construire des applications réactives. Il fournit des outils pour construire des applications HTTP, TCP, des flux de messages asynchrones, des clients SQL…

Netty est un framework pour le développement d’applications réseau client/serveur qui utilise des I/O non-bloquants. Vert.x utilise Netty pour la couche de transport HTTP ou TCP.

Chaque extension Quarkus va s’interfacer avec Vert.x pour utiliser les I/O threads de son event loop réactive et tirer parti des I/O non-bloquants.

images/quarkus-reactive-core.png

Source https://quarkus.io/guides/quarkus-reactive-architecture - CC BY 3.0

Une event loop (boucle d’événements en français) est un pattern de programmation réactive qui attend et distribue des événements ou des messages via une boucle de traitement qui sépare la réception d’un message et son traitement.

Quarkus propose de nombreuses extensions HTTP, certaines réactives (reactive routes, RESTEasy reactive) et d’autres impératives (RESTEasy Classic, Undertow).

Toutes vont s’intégrer à Vert.x qui va fournir la couche de routage HTTP. En fonction de la nature bloquante ou non de l’extension, l’exécution se fera directement dans un I/O thread de l’event loop pour les extensions réactives...

Mutiny

Mutiny est une bibliothèque de programmation intuitive et réactive. C’est le modèle principal pour écrire des applications réactives avec Quarkus.

Il existe de nombreuses bibliothèques de programmation réactives. Celles-ci fournissent des types réactifs qui peuvent être utilisés dans les différentes extensions réactives de Quarkus telles que le client HTTP ou le serveur JAX-RS.

Mutiny a une approche événementielle : vous recevez des événements auxquels vous réagissez, puis publiez de nouveaux événements.

Mutiny propose deux types réactifs :

  • Uni : qui représente une action asynchrone retournant 0 ou 1 résultat.

  • Multi : qui représente un flux d’événements, possiblement infini. Multi implémente Publisher de la spécification Reactive Streams ; il implémente donc de la back pressure. La back pressure est le fait de pouvoir faire varier le rythme de consommation d’un flux d’événements en fonction de la charge qu’implique son traitement. Par exemple, consommer moins rapidement des événements s’ils impliquent une grande charge CPU.

Mutiny fonctionne via un modèle de souscription ; vous définissez quelles actions réaliser pour quels événements (un élément...

Webservice REST réactif avec RESTEasy Reactive

Comme nous l’avons vu dans le chapitre Développement d’applications avec Quarkus, section Webservice REST avec JAX-RS, RESTEasy Reactive permet le développement de web services REST réactifs.

Dans l’exemple que nous avons utilisé jusqu’ici, chaque méthode était bloquante car retournait un objet ou void.

RESTEasy Reactive implémente ce qu’on appelle le smart dispatch : si la méthode retourne un objet ou void, son exécution sera faite dans un worker thread ; si elle retourne un type réactif (Uni, Multi, CompletionStage ou un Publisher de Reactive Streams), son exécution sera faite sur l’event loop dans un I/O thread. Ce comportement peut être surchargé via les annotations @Blocking ou @NonBlocking qui forcent l’exécution d’une méthode dans un worker thread ou un I/O thread.

Bien qu’il puisse y avoir des situations où l’on voudrait bloquer et retourner un type réactif, l’inverse doit être fait avec beaucoup de précautions au risque de bloquer l’event loop.

Une méthode annotée par @Transactional sera toujours considérée comme bloquante car l’API JTA est bloquante.

Une méthode non bloquante peut retourner un Uni<List<Product>> ; quand l’Uni sera résolue...

Base de données réactive avec Hibernate Reactive

1. Reactive SQL Clients

Pour utiliser une base de données avec Hibernate Reactive (aussi appelé Hibernate Rx), il faut tout d’abord ajouter un client SQL réactif qui correspond à la base de données que nous allons utiliser.

Quarkus fournit des extensions pour les clients réactifs des bases de données suivantes :

  • IBM Db2

  • PostgreSQL

  • MariaDB/MySQL

  • Microsoft SQL Server

  • Oracle

Tous ces clients réactifs sont basés sur Vert.x.

Nous allons utiliser l’extension pour la base de données PostgreSQL.

Vous pouvez ajouter l’extension Reactive PostgreSQL Client via :

  • la CLI Quarkus :

quarkus extension add reactive-pg-client 
  • le plugin Maven :

mvn quarkus:add-extension -Dextensions="reactive-pg-client" 

Ceci va ajouter la dépendance Maven suivante :

<dependency> 
    <groupId>io.quarkus</groupId> 
    <artifactId>quarkus-reactive-pg-client</artifactId> 
</dependency> 

Les clients SQL réactifs se configurent comme une datasource JDBC, sauf qu’ils utilisent la propriété de configuration quarkus.datasource.reactive.url au lieu de quarkus.datasource.jdbc.url. Certains offrent d’autres propriétés de configuration. Vous pouvez vous référer à la documentation en ligne pour plus d’informations : https://quarkus.io/guides/reactive-sql-clients

Nous allons configurer la base de données PostgreSQL avec le profil %prod pour profiter du dev service PostgreSQL :

%prod.quarkus.datasource.db-kind=postgresql 
%prod.quarkus.datasource.username=quarkus 
%prod.quarkus.datasource.password=quarkus 
%prod.quarkus.datasource.reactive.url=postgresql: 
//localhost:5432/chapitre6 

Ensuite, nous pouvons injecter un objet io.vertx.mutiny.pgclient. PgPool pour accéder à la base de données.

Uni<RowSet<Row>> rowSet = pgPool 
        .query("SELECT id, name FROM fruits ORDER BY name ASC") 
        .execute(); 

Ici nous accédons à la base de données de façon non bloquante mais avec une API bas niveau qui nous retourne un ensemble de lignes de base de données....

NoSQL réactif avec MongoDB

L’extension MongoDB Client fournie par Quarkus propose un client réactif et non bloquant qui encapsule le client MongoDB Reactive Streams et propose une API utilisant Mutiny. Ce client est inclus dans l’extension MongoDB Client. Pour l’utilisation et la configuration de cette extension, vous pouvez vous référer au chapitre L’accès aux bases de données, section NoSQL avec MongoDB.

Pour utiliser le client réactif, il faut injecter un objet de type io.quarkus.mongodb.reactive.ReactiveMongoClient :

@Inject 
ReactiveMongoClient mongoClient; 

Celui-ci va proposer les mêmes méthodes que le client Reactive Streams de MongoDB mais chaque méthode va retourner un Uni ou un Multi, ce qui permet de s’interfacer plus facilement avec les autres extensions réactives de Quarkus.

De même, l’extension MongoDB with Panache fournit une implémentation réactive pour les entités et repositories Panache via les classes ReactivePanacheMongoEntityBaseReactivePanacheMongoEntity, ReactivePanacheMongoRepositoryBase et ReactivePanacheMongoRepository.

En utilisant ces entités et repositories réactifs, chaque méthode va retourner un Uni qui devra ensuite être renvoyé par les méthodes du endpoint ProductResource. RESTEasy Reactive souscrira à cet Uni pour le résoudre.

Il est important...

REST Client réactif

Comme nous l’avons vu dans le chapitre Développement d’applications avec Quarkus, section Appel d’un autre service web avec le client REST, l’extension REST Client Reactive fournit un client HTTP réactif obéissant aux principes REST. Dans l’exemple que nous avions vu, chaque méthode était bloquante car retournait un objet ou void.

Ce REST Client implémente le même smart dispatch que RESTEasy Reactive : si une méthode retourne un objet ou void, elle est bloquante et s’exécute dans un worker thread ; si elle retourne un type réactif, elle est non bloquante et s’exécute dans un I/O thread de l’event loop.

Si nous reprenons l’exemple du chapitre Développement d’applications avec Quarkus, section Appel d’un autre service web avec le client REST, nous pouvons adapter le client REST PriceClient ainsi que la ressource ProductResource pour passer à une implémentation réactive.

Le PriceClient retournera un Uni<Price> au lieu d’un objet Price, ce qui fera automatiquement basculer son appel HTTP en mode non bloquant dans un I/O thread de l’event loop.

@Path("/prices") 
@RegisterRestClient(configKey = "prices-api") 
public interface PriceClient { 
    @GET 
    @Path("/{id}") ...

Reactive Routes

L’extension Reactive Routes est une des extensions HTTP de Quarkus. Elle permet de développer des endpoints HTTP légers et performants qui utilisent directement Eclipse Vert.x via un ensemble d’annotations.

Cette extension est plus légère que l’extension RESTEasy Reactive (et peut être un peu plus performante), mais offre moins de fonctionnalités et peut être plus difficile à utiliser pour faire des choses complexes. Si vous devez implémenter un service REST, RESTEasy Reactive est certainement plus adapté à vos besoins ; néanmoins, pour un endpoint HTTP simple ou pour une manipulation plus bas niveau du routeur Vert.x, cette extension peut être utile.

Vous pouvez ajouter l’extension Reactive Routes via :

  • la CLI Quarkus :

quarkus extension add reactive-routes 
  • le plugin Maven :

mvn quarkus:add-extension -Dextensions="reactive-routes" 

Ceci va ajouter la dépendance Maven suivante :

<dependency> 
    <groupId>io.quarkus</groupId> 
    <artifactId>quarkus-reactive-routes</artifactId> 
</dependency> 

Pour développer un endpoint HTTP avec Reactive Routes, nous allons créer un bean CDI qui utilisera l’annotation @Route. Cette annotation permet de définir des routes et se positionne au niveau des méthodes.

@Route permet de configurer les éléments suivants pour chaque route :

  • Son chemin via l’attribut path. Celui-ci peut contenir un paramètre de la forme :nom-du-param. On peut utiliser l’attribut regex à la place pour utiliser une expression régulière. Dans le cas où plusieurs routes correspondent à un même chemin, il est possible de les ordonner via l’attribut order

  • La ou les méthodes HTTP via l’attribut methods.

  • La gestion de contenu via les attributs produces et consumes.

Une méthode peut définir plusieurs routes.

Pour chaque méthode, nous pouvons injecter des paramètres...

Messaging réactif avec Apache Kafka

Comme nous l’avons vu en début de chapitre, une architecture réactive se caractérise par l’utilisation de messages asynchrones en remplacement d’appels synchrones. Pour cela, la communication entre services se fera avec des messages envoyés via un broker de messages plutôt que des appels HTTP synchrones.

Quarkus supporte les brokers de messages JMS (Java Message Service), AMQP (Advanced Message Queuing Protocol) et Apache Kafka.

La spécification Microprofile Reactive Messaging permet le développement d’applications événementielles et réactives via messages. Quarkus utilise l’extension SmallRye Reactive Messaging pour son implémentation. Celle-ci supporte les brokers Apache Kafka et AMQP 1.0.

Nous allons utiliser l’implémentation Apache Kafka dans cette section.

La spécification Microprofile Reactive Messaging fournit une API agnostique du broker de messages qui introduit les concepts suivants :

  • Message : les applications envoient et reçoivent des messages. Un message contient un corps (payload) et des métadonnées (metadatas).

  • Canal (channel) : les messages transitent dans un canal. Les applications se connectent à un canal pour publier ou consommer des messages.

  • Connecteur : les canaux se connectent à un broker de messages via un connecteur. Il existe différents connecteurs pour différentes technologies de broker.

L’extension SmallRye Reactive Messaging Kafka implémente Microprofile Reactive Messaging pour le broker de messages Apache Kafka. Il fournit un connecteur Kafka qui va envoyer des messages en tant que record (enregistrement en français) Kafka dans des canaux représentés par des topics.

Vous pouvez ajouter l’extension SmallRye Reactive Messaging Kafka via :

  • la CLI Quarkus :

quarkus extension add smallrye-reactive-messaging-kafka 
  • le plugin Maven :

mvn quarkus:add-extension -Dextensions="smallrye-reactive- 
messaging-kafka" 

Ceci va ajouter la dépendance Maven suivante :

<dependency> 
    <groupId>io.quarkus</groupId> 
    <artifactId>quarkus-smallrye-reactive-messaging-kafka</artifactId> 
</dependency> 

Cette extension fournit un dev service...