Ces derniers temps, la programmation réactive a gagné en popularité auprès de la communauté des développeurs et des clients en raison de sa capacité à concevoir des applications de manière déclarative, et non impérative, ce qui a entraîné des applications plus réactives et résilientes. Le fait que Spring 5 ait incorporé un système reactif dans son coeur a mis en évidence le changement de paradigme vers la programmation déclarative.
La programmation réactive gère les flux de données asynchrones entre les producteurs de données et les consommateurs qui doivent réagir à ces données de manière non bloquante. Ainsi, la programmation réactive est tout au sujet des applications non bloquantes qui sont asynchrones et pilotées par les événements et nécessitent un petit nombre de threads à l’échelle.
Les applications réactives sont difficiles à construire avec les frameworks à base de threads, car la mise à l’échelle d’une application basée sur un état mutable partagé, des threads et des verrous est très complexe.
Dans un contexte de programmation réactive, «Tout est un flux et agit de manière non bloquante lorsqu’il y a des données dans le flux».
Pourquoi la programmation réactive ?
Le niveau élevé d’abstraction avec la programmation réactive conduit à une lisibilité accrue du code afin que les développeurs puissent se concentrer principalement sur l’interdépendance des événements qui définissent la logique métier.
Les modèles réactifs s’intègrent naturellement au traitement des messages dans des environnements hautement concurrents, ce qui est un cas d’utilisation courant en entreprise. L’approche réactive est le meilleur moyen de contrôler le flux de trafic entre le producteur et le consommateur, ce qui permet d’éviter les problèmes de mémoire insuffisante.
Avec un ou plusieurs threads, les tâches liées à l’IO peuvent être effectuées de manière asynchrone et non bloquante sans bloquer le thread en cours. La programmation réactive peut gérer plus efficacement les situations où des applications hautement interactives et en temps réel, ou toute action / événement, peuvent déclencher une notification pour plusieurs sous-systèmes connectés.
Cas d’utilisation idéaux pour la mise en œuvre de la programmation réactive
- Un grand nombre de services de traitement des transactions, comme dans le secteur bancaire.
- Services de notification de grandes applications de commerce en ligne, comme Amazon.
- Une entreprise de commerce d’actions où les prix des actions changent simultanément.
Les streams réactifs
« Reactive Streams » définit une spécification d’API qui contient un ensemble minimal d’interfaces exposant des façons de définir des opérations et des entités pour des flux de données asynchrones avec une contre-pression non bloquante.
Avec l’introduction de la contre-pression, Reactive Streams permet à l’abonné de contrôler le taux d’échange de données des éditeurs.
L’API Reactive Streams fait officiellement partie de Java 9 en tant que java.util.concurrent.Flow.
Les flux réactifs sont principalement utilisés comme couche d’interopérabilité.
Les nouveautés de Spring 5 pour la programmation réactive
Tant le module réactive Spring-Web et Spring MVC soutiennent la même programmation @Controller, mais le module Spring-Web-réactive s’exécute en plus sur un moteur réactif et non-bloquant.
Le module Spring-Web-réactive et Spring MVC partagent de nombreux algorithmes communs, mais le module Spring-Web-réactive a redéfini la plupart des contrats Spring MVC, tels que HandlerMapping et HandlerAdapter, pour les rendre asynchrones et non bloquant ainsi que de permettre requête et réponse HTTP réactives (sous la forme de RouterFunction et HandlerFunction).
Le nouveau WebClient réactif a également été introduit dans Spring 5 en plus du RestTemplate existant.
Les clients HTTP (par exemple un Reactor, Netty, Undertow) qui prennent en charge la programmation réactive sont adaptés à un ensemble d’abstractions de ClientHttpRequest et ClientHttpResponse réactifs qui exposent la requête et le corps de la réponse en tant que flux<DataBuffer> avec un support complet de contre-pression au niveau de la lecture et l’écriture.
Spring 5 Framework a introduit Reactor comme implémentation pour la spécification des Strems réactifs.
Reactor est une librairie Reactive de dernière génération permettant de créer des applications non bloquantes sur la JVM.
Reactor étend le contrat de base Reactive Streams Publisher et définit les types de Flux et Mono API, pour fournir des opérations déclaratives sur des séquences de données de 0..N et 0..1 respectivement.
Spring Web Reactive utilise l’offre Servlet 3.1 pour les E / S non bloquantes et fonctionne sur les conteneurs Servlet 3.1.
Spring WebFlux propose un choix de deux modèles de programmation.
- Contrôleurs annotés: ils sont identiques à Spring MVC avec des annotations supplémentaires fournies par le module Spring-Web. Les deux contrôleurs Spring MVC et WebFlux prennent en charge les types de retour réactif. En outre, WebFlux prend également en charge les arguments reactifs @RequestBody.
- Modèle de programmation fonctionnelle: Une petite bibliothèque légère basée sur lambda qui expose les utilitaires à acheminer et gère les demandes.
Spring Web Reactive contre Spring Web MVC
Spring 5 héberge à la fois Spring Web Reactive (sous le module spring-web-reactive) et Spring Web MVC (sous le module spring-webmvc) l’un à côté de l’autre.
Bien que les modules Spring Web Reactive et Spring Web MVC partagent de nombreux algorithmes, ils ne partagent pas de code en raison de la capacité de Spring Web Reactive à s’exécuter sur une couche d’adaptateur HTTP Reactive Streams réactive et non bloquante.
L’exécution de Spring MVC nécessite des conteneurs Servlet, tandis que Spring Web Reactive s’exécute également sur des runtimes non-Servlet, comme sur Netty et Undertow.
Passer d’une application Spring MVC à Spring Web Reactive devrait être envisagé s’il existe une exigence absolue pour une stack web non bloquante, un framework web léger et fonctionnel à utiliser avec les lambdas de Java 8 ou Kotlin.
Configuration de base pour la programmation réactive
Ci-dessous le pom.xml avec la version M5 de 2.0.0 et une dépendance de WebFlux.
Approche traditionnelle ou approche réactive
Dans une approche traditionnelle, l’exécution sera bloquée et attendra la fin de l’exécution de votre service. Dans le code suivant, après la première instruction d’impression, l’exécution du programme sera bloquée et en attente de l’exécution du service. Après la fin de l’exécution du service, l’exécution du programme sera reprise et la deuxième instruction d’impression sera exécutée.
Dans une approche réactive, l’exécution du programme se poursuivra sans attendre l’achèvement de l’exécution du service. Dans le code suivant, après la première instruction d’impression, la deuxième instruction d’impression sera exécutée de manière non bloquante sans attendre l’achèvement de l’exécution du service. Le flux Flux sera renseigné avec la disponibilité des données produit.
Limites du printemps 5
- Le dépannage d’une application réactive est un peu difficile, et il est possible que, lors de la résolution d’un problème, vous ayez accidentellement bloqué le code qui a été introduit.
- La plupart des bibliothèques d’intégration Java traditionnelles bloquent toujours.
- Des options limitées sont disponibles pour les base de données réactives, à l’exception de quelques bases de données NoSQL telles que MongoDB.
Spring Security n’est toujours pas supporté.