From bfcce68c31c41ce70b15a5873a6bf0cb82b66b99 Mon Sep 17 00:00:00 2001 From: khairi Date: Wed, 27 Nov 2024 21:14:22 +0100 Subject: [PATCH 01/23] commit article about reactive programming --- _data/authors.yml | 17 ++- _posts/2024-11-23-programation-reactive.adoc | 111 +++++++++++++++++++ images/authors/khairikhadhraoui.jpg | Bin 0 -> 27228 bytes images/khairi/programation-reactive.png | Bin 0 -> 58958 bytes 4 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 _posts/2024-11-23-programation-reactive.adoc create mode 100644 images/authors/khairikhadhraoui.jpg create mode 100644 images/khairi/programation-reactive.png diff --git a/_data/authors.yml b/_data/authors.yml index 2801dc59..63b17fc3 100644 --- a/_data/authors.yml +++ b/_data/authors.yml @@ -253,4 +253,19 @@ Passionné de sport, il aime tout particulièrement le volley qu'il a pratiqué pagesciam: "https://www.sciam.fr/equipe/chaker-fezai" picture: chakerfezai.jpg socials: - linkedin: "chaker-fezai-31436318" \ No newline at end of file + linkedin: "chaker-fezai-31436318" + +khairikhadhraoui: + name: "Khairi Khadhraoui" + bio: "Diplômé en 2015 d’un diplôme d’ingénieur en spécialité système d’information à l’école polytechnique centrale de Tunis. + +Khairi a travaillé sur plusieurs projets au cours de ces dernier 8 ans principalement dans le secteur de télécommunication, bancaire et finance + +Khairi est passionné par les nouvelles technologiques spécialement au développement des application web. + +Ces centres d’intérêt se tourne principalement sur les randonné, les voyage et tous ce qui est lié à la nature." + job: "Consultant Technique Senior" + pagesciam: "https://www.sciam.fr/equipe/khairi-khadhraoui" + picture: khairikhadfhraoui.jpg + socials: + linkedin: "https://www.linkedin.com/in/khadhraoui-khairi-21940084/" \ No newline at end of file diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc new file mode 100644 index 00000000..2134b6e7 --- /dev/null +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -0,0 +1,111 @@ += La programmation réactive avec Reactor Spring web Flux +:showtitle: +:page-navtitle: La programmation réactive avec Reactor Spring web Flux +:page-excerpt: +:layout: post +:author: khairikhadhraoui +:page-tags: +:page-vignette: +:page-liquid: +:page-categories: software news + +Avant d'explorer la programmation réactive, il est utile de comprendre les systèmes non réactifs traditionnels et leurs inconvénients, en particulier en ce qui concerne l'utilisation des ressources et la gestion des événements. + +Les systèmes non réactifs, aussi appelés systèmes synchrones ou bloquants, sont les approches traditionnelles utilisées dans la programmation. Voici quelques caractéristiques clés: + + +Traitement séquentiel Une tâche doit généralement attendre la fin de l'exécution de la tâche précédente avant de commencer, + +Blocage des ressources : Les systèmes non réactifs bloquent souvent des ressources (comme des threads ou des connexions réseau) en attendant des résultats, + +Gestion des événements complexes : La gestion des événements dans les systèmes non réactifs peut devenir complexe et difficile à maintenir, surtout lorsque le nombre d'événements augmente + +Latence élevée : En raison de la nature bloquante de ces systèmes, ils peuvent entraîner une latence élevée, surtout dans les applications où la rapidité de réponse est cruciale. + +Scalabilité limitée : Comme chaque requête ou tâche peut nécessiter son propre thread ou processus, l'augmentation du nombre de requêtes peut rapidement saturer les ressources du système + + + +Pour surmonter ces limitations, les systèmes réactifs offrent une alternative en se concentrant sur l'asynchronisme, la non-bloquante, et l'efficacité dans l'utilisation des ressources. Ils permettent de créer des applications qui sont plus réactives, plus résilientes, et plus scalables, en répondant efficacement aux événements et en utilisant les ressources de manière optimale. + +== Principes programmation réactive + +Principes programmation réactive + +Les principes de la programmation réactive sont encapsulés dans le "Manifeste Réactif", qui énonce quatre caractéristiques clés : + +Responsive (Réactif) : Les systèmes réactifs répondent rapidement aux utilisateurs pour garantir une expérience fluide et interactive. + +Resilient (Résilient) : Les systèmes réactifs restent opérationnels même en cas de défaillance, grâce à des mécanismes de gestion des erreurs et de redondance. + +Elastic (Élastique) : Les systèmes réactifs s'adaptent aux variations de la charge de travail en allouant dynamiquement les ressources nécessaires. + +Message-Driven (Basé sur les Messages) : Les systèmes réactifs communiquent par la transmission de messages asynchrones, facilitant la déconnexion et le découplage des composants. + +== Standard de la programmation réactive + +Les standards de la programmation réactive sont basés sur deux modèles. + +ReactiveX à été conçu pour fournir une API unifiée pour le traitement de collections asynchrones, en s'inspirant des méthodes des collections synchrones (comme map, filter, reduce). Il est souvent utilisé pour gérer des événements utilisateur, des requêtes réseau, et d'autres opérations asynchrones dans des applications interactives. Ces implémentations connues sont : RxJava et RxJs. + +Reactive Streams Il a été créé pour résoudre des problèmes spécifiques de backpressure dans les systèmes de traitement de données asynchrones, en définissant un ensemble minimal d'interfaces pour garantir une gestion cohérente et efficace des flux de données entre différentes bibliothèques réactives dans l'écosystème JVM. Ces implementation connues sont Akka Reactor Vertex et RxJAVA2 + +Dans notre article, on va s'intéresser à Reactor qui est une implémentation de Reactive streams. + +Les objectifs principaux de Reactive Streams sont : + +Asynchronisme : Gérer les flux de données de manière non bloquante et asynchrone. + +Backpressure : Introduire une rétropression pour permettre aux consommateurs de signaler aux producteurs leur capacité à traiter les données, évitant ainsi les surcharges. + +Interopérabilité : Fournir une interface standard pour que différentes bibliothèques réactives puissent fonctionner ensemble. + +Interfaces principales de Reactive Streams : + +Publisher : Représente une source qui peut émettre une séquence de valeurs asynchrones. Les éditeurs appellent la méthode subscribe() pour permettre aux abonnés de recevoir les éléments. + +Subscriber : Représente un consommateur de données. Il reçoit les éléments émis par un Publisher via quatre méthodes : onSubscribe(), onNext(), onError(), et onComplete(). + +Subscription : Gère le lien entre un Publisher et un Subscriber. Elle permet de demander des éléments (request(long n)) ou d'annuler la souscription (cancel()). + +Processor : Combine les fonctionnalités d'un Publisher et d'un Subscriber. Un Processor reçoit des éléments, les traite, et les renvoie sous forme d'un autre flux. + +== Project Reactor : + +Reactor est une bibliothèque réactive pour Java développée par Pivotal (maintenant VMware) et intégrée dans l'écosystème Spring. Elle fournit une implémentation de Reactive Streams et permet de construire des applications non bloquantes, asynchrones, et scalables. Reactor est au cœur de Spring WebFlux, le module réactif de Spring Framework. + +Les principales abstractions fournies par Reactor sont : + +Mono : Représente un flux réactif qui produit au maximum une seule valeur ou une erreur. + +Flux : Représente un flux réactif qui peut émettre zéro, une ou plusieurs valeurs, voire un flux infini. + +Ces deux types sont les composants de base utilisés pour modéliser des flux de données asynchrones en Java avec Reactor. + +En pratique un Flux peut être sérialisé sous plusieur formes + +Json Array : retourne un arrayList normale + +text Event Stream : envoie un flux d'objets Json contenue donnés par donne dès qu’ils sont disponible. + +flux de json stream : De la même manière entre deux serveurs on peut avoir un flux de json Stream. + +== Spring Web Flux avec Reactor + +Spring web flux fait partie de projet Spring 5 c'est un module Spring basé sur une api http exposé à la source sur reactive Streams. dans lequel on continue à utiliser les mêmes annotation du contrôleurs Spring MVC (@conttreler, @RequestMapping, etc.) sauf que au lieu d'utiliser des type de retour List, T ou void, on utilise Flux ou Mono. + +Composants de Spring WebFlux + +Contrôleurs Réactifs : Comme dans Spring MVC, mais avec des types réactifs comme Mono et Flux. + +WebClient : Un client HTTP non-bloquant qui remplace RestTemplate pour les appels externes réactifs. + +Router Function : Une approche fonctionnelle pour définir des routes HTTP. + +Avantages: + +Scalabilité : La nature non-bloquante permet de gérer un grand nombre de connexions simultanées avec moins de threads. + +Performance : Idéal pour les applications nécessitant une faible latence et une haute performance. + +Flexibilité : Peut être utilisé pour des microservices, des applications Web, ou même des applications fonctionnant avec d'autres paradigmes réactifs comme RxJava. \ No newline at end of file diff --git a/images/authors/khairikhadhraoui.jpg b/images/authors/khairikhadhraoui.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dd3683cd7a441755b3da95aa28663eb982aa34f3 GIT binary patch literal 27228 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

!R1=7m@ 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 Date: Wed, 27 Nov 2024 21:17:47 +0100 Subject: [PATCH 02/23] modify design article and add conclusion --- _posts/2024-11-23-programation-reactive.adoc | 139 ++++++++++++++++--- 1 file changed, 120 insertions(+), 19 deletions(-) diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc index 2134b6e7..a6a3682a 100644 --- a/_posts/2024-11-23-programation-reactive.adoc +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -5,10 +5,11 @@ :layout: post :author: khairikhadhraoui :page-tags: -:page-vignette: +:page-vignette: programation-reactive.jpg :page-liquid: :page-categories: software news +==Introduction: Avant d'explorer la programmation réactive, il est utile de comprendre les systèmes non réactifs traditionnels et leurs inconvénients, en particulier en ce qui concerne l'utilisation des ressources et la gestion des événements. Les systèmes non réactifs, aussi appelés systèmes synchrones ou bloquants, sont les approches traditionnelles utilisées dans la programmation. Voici quelques caractéristiques clés: @@ -32,23 +33,25 @@ Pour surmonter ces limitations, les systèmes réactifs offrent une alternative Principes programmation réactive -Les principes de la programmation réactive sont encapsulés dans le "Manifeste Réactif", qui énonce quatre caractéristiques clés : +===Les principes de la programmation réactive sont encapsulés dans le "Manifeste Réactif", qui énonce quatre caractéristiques clés : -Responsive (Réactif) : Les systèmes réactifs répondent rapidement aux utilisateurs pour garantir une expérience fluide et interactive. +===Responsive (Réactif) : Les systèmes réactifs répondent rapidement aux utilisateurs pour garantir une expérience fluide et interactive. -Resilient (Résilient) : Les systèmes réactifs restent opérationnels même en cas de défaillance, grâce à des mécanismes de gestion des erreurs et de redondance. +===Resilient (Résilient) : Les systèmes réactifs restent opérationnels même en cas de défaillance, grâce à des mécanismes de gestion des erreurs et de redondance. -Elastic (Élastique) : Les systèmes réactifs s'adaptent aux variations de la charge de travail en allouant dynamiquement les ressources nécessaires. +===Elastic (Élastique) : Les systèmes réactifs s'adaptent aux variations de la charge de travail en allouant dynamiquement les ressources nécessaires. -Message-Driven (Basé sur les Messages) : Les systèmes réactifs communiquent par la transmission de messages asynchrones, facilitant la déconnexion et le découplage des composants. +===Message-Driven (Basé sur les Messages) : Les systèmes réactifs communiquent par la transmission de messages asynchrones, facilitant la déconnexion et le découplage des composants. == Standard de la programmation réactive Les standards de la programmation réactive sont basés sur deux modèles. -ReactiveX à été conçu pour fournir une API unifiée pour le traitement de collections asynchrones, en s'inspirant des méthodes des collections synchrones (comme map, filter, reduce). Il est souvent utilisé pour gérer des événements utilisateur, des requêtes réseau, et d'autres opérations asynchrones dans des applications interactives. Ces implémentations connues sont : RxJava et RxJs. +===ReactiveX: + ReactiveX à été conçu pour fournir une API unifiée pour le traitement de collections asynchrones, en s'inspirant des méthodes des collections synchrones (comme map, filter, reduce). Il est souvent utilisé pour gérer des événements utilisateur, des requêtes réseau, et d'autres opérations asynchrones dans des applications interactives. Ces implémentations connues sont : RxJava et RxJs. -Reactive Streams Il a été créé pour résoudre des problèmes spécifiques de backpressure dans les systèmes de traitement de données asynchrones, en définissant un ensemble minimal d'interfaces pour garantir une gestion cohérente et efficace des flux de données entre différentes bibliothèques réactives dans l'écosystème JVM. Ces implementation connues sont Akka Reactor Vertex et RxJAVA2 +===Reactive Streams: + Reactive Streams a été créé pour résoudre des problèmes spécifiques de backpressure dans les systèmes de traitement de données asynchrones, en définissant un ensemble minimal d'interfaces pour garantir une gestion cohérente et efficace des flux de données entre différentes bibliothèques réactives dans l'écosystème JVM. Ces implementation connues sont Akka Reactor Vertex et RxJAVA2 Dans notre article, on va s'intéresser à Reactor qui est une implémentation de Reactive streams. @@ -76,36 +79,134 @@ Reactor est une bibliothèque réactive pour Java développée par Pivotal (main Les principales abstractions fournies par Reactor sont : -Mono : Représente un flux réactif qui produit au maximum une seule valeur ou une erreur. +===Mono : Représente un flux réactif qui produit au maximum une seule valeur ou une erreur. -Flux : Représente un flux réactif qui peut émettre zéro, une ou plusieurs valeurs, voire un flux infini. +===Flux : Représente un flux réactif qui peut émettre zéro, une ou plusieurs valeurs, voire un flux infini. Ces deux types sont les composants de base utilisés pour modéliser des flux de données asynchrones en Java avec Reactor. En pratique un Flux peut être sérialisé sous plusieur formes -Json Array : retourne un arrayList normale +-Json Array : retourne un arrayList normale -text Event Stream : envoie un flux d'objets Json contenue donnés par donne dès qu’ils sont disponible. +-Text Event Stream : envoie un flux d'objets Json contenue donnés par donne dès qu’ils sont disponible. -flux de json stream : De la même manière entre deux serveurs on peut avoir un flux de json Stream. +-Flux de json stream : De la même manière entre deux serveurs on peut avoir un flux de json Stream. == Spring Web Flux avec Reactor Spring web flux fait partie de projet Spring 5 c'est un module Spring basé sur une api http exposé à la source sur reactive Streams. dans lequel on continue à utiliser les mêmes annotation du contrôleurs Spring MVC (@conttreler, @RequestMapping, etc.) sauf que au lieu d'utiliser des type de retour List, T ou void, on utilise Flux ou Mono. -Composants de Spring WebFlux +===Composants de Spring WebFlux -Contrôleurs Réactifs : Comme dans Spring MVC, mais avec des types réactifs comme Mono et Flux. +-Contrôleurs Réactifs : Comme dans Spring MVC, mais avec des types réactifs comme Mono et Flux. -WebClient : Un client HTTP non-bloquant qui remplace RestTemplate pour les appels externes réactifs. +-WebClient : Un client HTTP non-bloquant qui remplace RestTemplate pour les appels externes réactifs. -Router Function : Une approche fonctionnelle pour définir des routes HTTP. +R-outer Function : Une approche fonctionnelle pour définir des routes HTTP. -Avantages: +====Avantages: Scalabilité : La nature non-bloquante permet de gérer un grand nombre de connexions simultanées avec moins de threads. Performance : Idéal pour les applications nécessitant une faible latence et une haute performance. -Flexibilité : Peut être utilisé pour des microservices, des applications Web, ou même des applications fonctionnant avec d'autres paradigmes réactifs comme RxJava. \ No newline at end of file +Flexibilité : Peut être utilisé pour des microservices, des applications Web, ou même des applications fonctionnant avec d'autres paradigmes réactifs comme RxJava. + +Configuration d'un projet Spring WebFlux + +Maven : + +Pour configurer un projet Maven avec Spring WebFlux et Reactor, il est essentiel d'ajouter les dépendances appropriées dans le fichier pom.xml. Voici les étapes à suivre pour inclure ces dépendances. +[source,plain] +---- + + org.springframework.boot + spring-boot-starter-webflux + + + + org.projectreactor + reactor-spring + 1.0.1.RELEASE + + +----- +===Création d'un contrôleur réactif: + + +[source,plain] +---- +@RestController + + public class ReactiveController { + + @GetMapping("/hello") + +public Mono sayHello() { + +return Mono.just("Hello, WebFlux!"); + + } +----- +[source,plain] +---- +@GetMapping("/numbers") + +public Flux getNumbers() { + +return Flux.range(1, 10) .delayElements(Duration.ofMillis(100)); + +} + +} +----- +===Exemple d'utilisation de WebClient : +[source,plain] +---- +public class WebClientExample { + + private final WebClient webClient =WebClient.create("http://example.com"); + + public Mono fetchData() { + + return webClient.get() .uri("/api/data") .retrieve() + +.bodyToMono(String.class); + +} + + } +----- +===Gestion du Backpressure + +Le backpressure est une composante essentielle dans les systèmes réactifs pour gérer le flux de données entre les producteurs et les consommateurs. Avec Reactor, vous pouvez contrôler le backpressure via des opérateurs comme limitRate. + +Exemple d'utilisation de limitRate pour réguler la consommation des données : + +[source,plain] +---- + +Flux flux = WebClient.create("http://example.com") + +.get() + +.uri("/api/large-stream") + +.retrieve() .bodyToFlux(Integer.class) + +.limitRate(5); + + flux.subscribe(data -> { // Traitement des données + +System.out.println("Received: " + data); + +}); + +------- + +==Conclusion + +Spring Reactor propulse le développement d'applications modernes vers de nouveaux sommets en leur conférant réactivité, performance et résilience. En s'alignant sur le Reactive Manifesto, cette technologie ouvre la voie à des systèmes distribués agiles et efficaces. Toutefois, son adoption requiert une solide compréhension des concepts fondamentaux et une évaluation minutieuse des besoins spécifiques de chaque projet. + +Face à l'évolution rapide des architectures modernes (cloud, microservices, événements), la programmation réactive s'impose comme une approche incontournable. Il est passionnant d'envisager les prochaines avancées dans ce domaine et d'imaginer les nouveaux outils qui transformeront encore davantage notre façon de concevoir des systèmes réactifs. \ No newline at end of file From 35954c30ac37a5152d3b9df35d6405c629d629f9 Mon Sep 17 00:00:00 2001 From: khairi Date: Wed, 27 Nov 2024 21:27:14 +0100 Subject: [PATCH 03/23] modify design article --- _posts/2024-11-23-programation-reactive.adoc | 108 ++++++++----------- 1 file changed, 46 insertions(+), 62 deletions(-) diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc index a6a3682a..2b2f19d7 100644 --- a/_posts/2024-11-23-programation-reactive.adoc +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -10,6 +10,7 @@ :page-categories: software news ==Introduction: + Avant d'explorer la programmation réactive, il est utile de comprendre les systèmes non réactifs traditionnels et leurs inconvénients, en particulier en ce qui concerne l'utilisation des ressources et la gestion des événements. Les systèmes non réactifs, aussi appelés systèmes synchrones ou bloquants, sont les approches traditionnelles utilisées dans la programmation. Voici quelques caractéristiques clés: @@ -33,24 +34,24 @@ Pour surmonter ces limitations, les systèmes réactifs offrent une alternative Principes programmation réactive -===Les principes de la programmation réactive sont encapsulés dans le "Manifeste Réactif", qui énonce quatre caractéristiques clés : +=== Les principes de la programmation réactive sont encapsulés dans le "Manifeste Réactif", qui énonce quatre caractéristiques clés : -===Responsive (Réactif) : Les systèmes réactifs répondent rapidement aux utilisateurs pour garantir une expérience fluide et interactive. +=== Responsive (Réactif) : Les systèmes réactifs répondent rapidement aux utilisateurs pour garantir une expérience fluide et interactive. -===Resilient (Résilient) : Les systèmes réactifs restent opérationnels même en cas de défaillance, grâce à des mécanismes de gestion des erreurs et de redondance. +=== Resilient (Résilient) : Les systèmes réactifs restent opérationnels même en cas de défaillance, grâce à des mécanismes de gestion des erreurs et de redondance. -===Elastic (Élastique) : Les systèmes réactifs s'adaptent aux variations de la charge de travail en allouant dynamiquement les ressources nécessaires. +=== Elastic (Élastique) : Les systèmes réactifs s'adaptent aux variations de la charge de travail en allouant dynamiquement les ressources nécessaires. -===Message-Driven (Basé sur les Messages) : Les systèmes réactifs communiquent par la transmission de messages asynchrones, facilitant la déconnexion et le découplage des composants. +=== Message-Driven (Basé sur les Messages) : Les systèmes réactifs communiquent par la transmission de messages asynchrones, facilitant la déconnexion et le découplage des composants. == Standard de la programmation réactive Les standards de la programmation réactive sont basés sur deux modèles. -===ReactiveX: +=== ReactiveX: ReactiveX à été conçu pour fournir une API unifiée pour le traitement de collections asynchrones, en s'inspirant des méthodes des collections synchrones (comme map, filter, reduce). Il est souvent utilisé pour gérer des événements utilisateur, des requêtes réseau, et d'autres opérations asynchrones dans des applications interactives. Ces implémentations connues sont : RxJava et RxJs. -===Reactive Streams: +=== Reactive Streams: Reactive Streams a été créé pour résoudre des problèmes spécifiques de backpressure dans les systèmes de traitement de données asynchrones, en définissant un ensemble minimal d'interfaces pour garantir une gestion cohérente et efficace des flux de données entre différentes bibliothèques réactives dans l'écosystème JVM. Ces implementation connues sont Akka Reactor Vertex et RxJAVA2 Dans notre article, on va s'intéresser à Reactor qui est une implémentation de Reactive streams. @@ -79,9 +80,9 @@ Reactor est une bibliothèque réactive pour Java développée par Pivotal (main Les principales abstractions fournies par Reactor sont : -===Mono : Représente un flux réactif qui produit au maximum une seule valeur ou une erreur. +=== Mono : Représente un flux réactif qui produit au maximum une seule valeur ou une erreur. -===Flux : Représente un flux réactif qui peut émettre zéro, une ou plusieurs valeurs, voire un flux infini. +=== Flux : Représente un flux réactif qui peut émettre zéro, une ou plusieurs valeurs, voire un flux infini. Ces deux types sont les composants de base utilisés pour modéliser des flux de données asynchrones en Java avec Reactor. @@ -97,7 +98,7 @@ En pratique un Flux peut être sérialisé sous plusieur formes Spring web flux fait partie de projet Spring 5 c'est un module Spring basé sur une api http exposé à la source sur reactive Streams. dans lequel on continue à utiliser les mêmes annotation du contrôleurs Spring MVC (@conttreler, @RequestMapping, etc.) sauf que au lieu d'utiliser des type de retour List, T ou void, on utilise Flux ou Mono. -===Composants de Spring WebFlux +=== Composants de Spring WebFlux -Contrôleurs Réactifs : Comme dans Spring MVC, mais avec des types réactifs comme Mono et Flux. @@ -105,7 +106,7 @@ Spring web flux fait partie de projet Spring 5 c'est un module Spring basé sur R-outer Function : Une approche fonctionnelle pour définir des routes HTTP. -====Avantages: +==== Avantages: Scalabilité : La nature non-bloquante permet de gérer un grand nombre de connexions simultanées avec moins de threads. @@ -115,7 +116,7 @@ Flexibilité : Peut être utilisé pour des microservices, des applications Web, Configuration d'un projet Spring WebFlux -Maven : +== Configuration Maven : Pour configurer un projet Maven avec Spring WebFlux et Reactor, il est essentiel d'ajouter les dépendances appropriées dans le fichier pom.xml. Voici les étapes à suivre pour inclure ces dépendances. [source,plain] @@ -130,82 +131,65 @@ Pour configurer un projet Maven avec Spring WebFlux et Reactor, il est essentiel reactor-spring 1.0.1.RELEASE +---- ------ -===Création d'un contrôleur réactif: +=== Création d'un contrôleur réactif: -[source,plain] +[source,java] ---- @RestController public class ReactiveController { - - @GetMapping("/hello") - -public Mono sayHello() { - -return Mono.just("Hello, WebFlux!"); - + @GetMapping("/hello") + public Mono sayHello() { + return Mono.just("Hello, WebFlux!"); } ------ -[source,plain] ---- -@GetMapping("/numbers") - -public Flux getNumbers() { - -return Flux.range(1, 10) .delayElements(Duration.ofMillis(100)); - -} +[source,java] +---- +@GetMapping("/numbers") + public Flux getNumbers() { + return Flux.range(1, 10) .delayElements(Duration.ofMillis(100)); + } } ------ -===Exemple d'utilisation de WebClient : -[source,plain] ---- -public class WebClientExample { - - private final WebClient webClient =WebClient.create("http://example.com"); - public Mono fetchData() { - - return webClient.get() .uri("/api/data") .retrieve() - -.bodyToMono(String.class); - -} +=== Exemple d'utilisation de WebClient : +[source,java] +---- +public class WebClientExample { + private final WebClient webClient =WebClient.create("http://example.com"); + public Mono fetchData() { + return webClient.get() .uri("/api/data") .retrieve() + .bodyToMono(String.class); + } } ------ -===Gestion du Backpressure +---- + +=== Gestion du Backpressure Le backpressure est une composante essentielle dans les systèmes réactifs pour gérer le flux de données entre les producteurs et les consommateurs. Avec Reactor, vous pouvez contrôler le backpressure via des opérateurs comme limitRate. Exemple d'utilisation de limitRate pour réguler la consommation des données : -[source,plain] +[source,java] ---- Flux flux = WebClient.create("http://example.com") - -.get() - -.uri("/api/large-stream") - -.retrieve() .bodyToFlux(Integer.class) - -.limitRate(5); - - flux.subscribe(data -> { // Traitement des données - -System.out.println("Received: " + data); - + .get() + .uri("/api/large-stream") + .retrieve() .bodyToFlux(Integer.class) + .limitRate(5); + flux.subscribe(data -> { // Traitement des données + System.out.println("Received: " + data); }); -------- +---- -==Conclusion +== Conclusion Spring Reactor propulse le développement d'applications modernes vers de nouveaux sommets en leur conférant réactivité, performance et résilience. En s'alignant sur le Reactive Manifesto, cette technologie ouvre la voie à des systèmes distribués agiles et efficaces. Toutefois, son adoption requiert une solide compréhension des concepts fondamentaux et une évaluation minutieuse des besoins spécifiques de chaque projet. From a801e7c6bcc3fc1d26044038ed88cd58cf595e24 Mon Sep 17 00:00:00 2001 From: khairi Date: Wed, 27 Nov 2024 21:30:02 +0100 Subject: [PATCH 04/23] modify design article --- _posts/2024-11-23-programation-reactive.adoc | 22 ++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc index 2b2f19d7..d54f6526 100644 --- a/_posts/2024-11-23-programation-reactive.adoc +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -9,7 +9,7 @@ :page-liquid: :page-categories: software news -==Introduction: +== Introduction: Avant d'explorer la programmation réactive, il est utile de comprendre les systèmes non réactifs traditionnels et leurs inconvénients, en particulier en ce qui concerne l'utilisation des ressources et la gestion des événements. @@ -34,24 +34,34 @@ Pour surmonter ces limitations, les systèmes réactifs offrent une alternative Principes programmation réactive -=== Les principes de la programmation réactive sont encapsulés dans le "Manifeste Réactif", qui énonce quatre caractéristiques clés : +Les principes de la programmation réactive sont encapsulés dans le "Manifeste Réactif", qui énonce quatre caractéristiques clés : -=== Responsive (Réactif) : Les systèmes réactifs répondent rapidement aux utilisateurs pour garantir une expérience fluide et interactive. +=== Responsive (Réactif) : + + Les systèmes réactifs répondent rapidement aux utilisateurs pour garantir une expérience fluide et interactive. -=== Resilient (Résilient) : Les systèmes réactifs restent opérationnels même en cas de défaillance, grâce à des mécanismes de gestion des erreurs et de redondance. +=== Resilient (Résilient) : + + Les systèmes réactifs restent opérationnels même en cas de défaillance, grâce à des mécanismes de gestion des erreurs et de redondance. -=== Elastic (Élastique) : Les systèmes réactifs s'adaptent aux variations de la charge de travail en allouant dynamiquement les ressources nécessaires. +=== Elastic (Élastique) : + + Les systèmes réactifs s'adaptent aux variations de la charge de travail en allouant dynamiquement les ressources nécessaires. -=== Message-Driven (Basé sur les Messages) : Les systèmes réactifs communiquent par la transmission de messages asynchrones, facilitant la déconnexion et le découplage des composants. +=== Message-Driven (Basé sur les Messages) : + + Les systèmes réactifs communiquent par la transmission de messages asynchrones, facilitant la déconnexion et le découplage des composants. == Standard de la programmation réactive Les standards de la programmation réactive sont basés sur deux modèles. === ReactiveX: + ReactiveX à été conçu pour fournir une API unifiée pour le traitement de collections asynchrones, en s'inspirant des méthodes des collections synchrones (comme map, filter, reduce). Il est souvent utilisé pour gérer des événements utilisateur, des requêtes réseau, et d'autres opérations asynchrones dans des applications interactives. Ces implémentations connues sont : RxJava et RxJs. === Reactive Streams: + Reactive Streams a été créé pour résoudre des problèmes spécifiques de backpressure dans les systèmes de traitement de données asynchrones, en définissant un ensemble minimal d'interfaces pour garantir une gestion cohérente et efficace des flux de données entre différentes bibliothèques réactives dans l'écosystème JVM. Ces implementation connues sont Akka Reactor Vertex et RxJAVA2 Dans notre article, on va s'intéresser à Reactor qui est une implémentation de Reactive streams. From d35d23aaa068ca45cf6afcfcf82af182df79a0b1 Mon Sep 17 00:00:00 2001 From: khairi Date: Wed, 27 Nov 2024 21:32:48 +0100 Subject: [PATCH 05/23] modify design article --- _posts/2024-11-23-programation-reactive.adoc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc index d54f6526..625ae52f 100644 --- a/_posts/2024-11-23-programation-reactive.adoc +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -36,19 +36,19 @@ Principes programmation réactive Les principes de la programmation réactive sont encapsulés dans le "Manifeste Réactif", qui énonce quatre caractéristiques clés : -=== Responsive (Réactif) : + Responsive (Réactif) : Les systèmes réactifs répondent rapidement aux utilisateurs pour garantir une expérience fluide et interactive. -=== Resilient (Résilient) : + Resilient (Résilient) : Les systèmes réactifs restent opérationnels même en cas de défaillance, grâce à des mécanismes de gestion des erreurs et de redondance. -=== Elastic (Élastique) : + Elastic (Élastique) : Les systèmes réactifs s'adaptent aux variations de la charge de travail en allouant dynamiquement les ressources nécessaires. -=== Message-Driven (Basé sur les Messages) : + Message-Driven (Basé sur les Messages) : Les systèmes réactifs communiquent par la transmission de messages asynchrones, facilitant la déconnexion et le découplage des composants. @@ -56,11 +56,11 @@ Les principes de la programmation réactive sont encapsulés dans le "Manifeste Les standards de la programmation réactive sont basés sur deux modèles. -=== ReactiveX: + ReactiveX: ReactiveX à été conçu pour fournir une API unifiée pour le traitement de collections asynchrones, en s'inspirant des méthodes des collections synchrones (comme map, filter, reduce). Il est souvent utilisé pour gérer des événements utilisateur, des requêtes réseau, et d'autres opérations asynchrones dans des applications interactives. Ces implémentations connues sont : RxJava et RxJs. -=== Reactive Streams: + Reactive Streams: Reactive Streams a été créé pour résoudre des problèmes spécifiques de backpressure dans les systèmes de traitement de données asynchrones, en définissant un ensemble minimal d'interfaces pour garantir une gestion cohérente et efficace des flux de données entre différentes bibliothèques réactives dans l'écosystème JVM. Ces implementation connues sont Akka Reactor Vertex et RxJAVA2 From bff319fffc9ea928a1eb19205613e77ad5b20850 Mon Sep 17 00:00:00 2001 From: khairi Date: Wed, 27 Nov 2024 21:34:00 +0100 Subject: [PATCH 06/23] modify design article --- _posts/2024-11-23-programation-reactive.adoc | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc index 625ae52f..bbff9436 100644 --- a/_posts/2024-11-23-programation-reactive.adoc +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -36,17 +36,11 @@ Principes programmation réactive Les principes de la programmation réactive sont encapsulés dans le "Manifeste Réactif", qui énonce quatre caractéristiques clés : - Responsive (Réactif) : - - Les systèmes réactifs répondent rapidement aux utilisateurs pour garantir une expérience fluide et interactive. + Responsive (Réactif) : Les systèmes réactifs répondent rapidement aux utilisateurs pour garantir une expérience fluide et interactive. - Resilient (Résilient) : - - Les systèmes réactifs restent opérationnels même en cas de défaillance, grâce à des mécanismes de gestion des erreurs et de redondance. + Resilient (Résilient) : Les systèmes réactifs restent opérationnels même en cas de défaillance, grâce à des mécanismes de gestion des erreurs et de redondance. - Elastic (Élastique) : - - Les systèmes réactifs s'adaptent aux variations de la charge de travail en allouant dynamiquement les ressources nécessaires. + Elastic (Élastique) : Les systèmes réactifs s'adaptent aux variations de la charge de travail en allouant dynamiquement les ressources nécessaires. Message-Driven (Basé sur les Messages) : @@ -56,13 +50,9 @@ Les principes de la programmation réactive sont encapsulés dans le "Manifeste Les standards de la programmation réactive sont basés sur deux modèles. - ReactiveX: - - ReactiveX à été conçu pour fournir une API unifiée pour le traitement de collections asynchrones, en s'inspirant des méthodes des collections synchrones (comme map, filter, reduce). Il est souvent utilisé pour gérer des événements utilisateur, des requêtes réseau, et d'autres opérations asynchrones dans des applications interactives. Ces implémentations connues sont : RxJava et RxJs. + ReactiveX: ReactiveX à été conçu pour fournir une API unifiée pour le traitement de collections asynchrones, en s'inspirant des méthodes des collections synchrones (comme map, filter, reduce). Il est souvent utilisé pour gérer des événements utilisateur, des requêtes réseau, et d'autres opérations asynchrones dans des applications interactives. Ces implémentations connues sont : RxJava et RxJs. - Reactive Streams: - - Reactive Streams a été créé pour résoudre des problèmes spécifiques de backpressure dans les systèmes de traitement de données asynchrones, en définissant un ensemble minimal d'interfaces pour garantir une gestion cohérente et efficace des flux de données entre différentes bibliothèques réactives dans l'écosystème JVM. Ces implementation connues sont Akka Reactor Vertex et RxJAVA2 + Reactive Streams: Reactive Streams a été créé pour résoudre des problèmes spécifiques de backpressure dans les systèmes de traitement de données asynchrones, en définissant un ensemble minimal d'interfaces pour garantir une gestion cohérente et efficace des flux de données entre différentes bibliothèques réactives dans l'écosystème JVM. Ces implementation connues sont Akka Reactor Vertex et RxJAVA2 Dans notre article, on va s'intéresser à Reactor qui est une implémentation de Reactive streams. From 4e48fa5da683b5d040a1b2a87bd94bd3df223e05 Mon Sep 17 00:00:00 2001 From: khairi Date: Wed, 27 Nov 2024 21:39:21 +0100 Subject: [PATCH 07/23] modify design article --- _posts/2024-11-23-programation-reactive.adoc | 22 +++++++++----------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc index bbff9436..f769c61c 100644 --- a/_posts/2024-11-23-programation-reactive.adoc +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -32,27 +32,25 @@ Pour surmonter ces limitations, les systèmes réactifs offrent une alternative == Principes programmation réactive -Principes programmation réactive +Les principes de la programmation réactive sont encapsulés dans le "Manifeste Réactif", qui énonce quatre caractéristiques clés{nbsp}: -Les principes de la programmation réactive sont encapsulés dans le "Manifeste Réactif", qui énonce quatre caractéristiques clés : +* _Responsive (Réactif) : Les systèmes réactifs répondent rapidement aux utilisateurs pour garantir une expérience fluide et interactive. - Responsive (Réactif) : Les systèmes réactifs répondent rapidement aux utilisateurs pour garantir une expérience fluide et interactive. +* _Resilient (Résilient) : Les systèmes réactifs restent opérationnels même en cas de défaillance, grâce à des mécanismes de gestion des erreurs et de redondance. - Resilient (Résilient) : Les systèmes réactifs restent opérationnels même en cas de défaillance, grâce à des mécanismes de gestion des erreurs et de redondance. +* _Elastic (Élastique) : Les systèmes réactifs s'adaptent aux variations de la charge de travail en allouant dynamiquement les ressources nécessaires. - Elastic (Élastique) : Les systèmes réactifs s'adaptent aux variations de la charge de travail en allouant dynamiquement les ressources nécessaires. - - Message-Driven (Basé sur les Messages) : +Message-Driven (Basé sur les Messages) : - Les systèmes réactifs communiquent par la transmission de messages asynchrones, facilitant la déconnexion et le découplage des composants. +Les systèmes réactifs communiquent par la transmission de messages asynchrones, facilitant la déconnexion et le découplage des composants. -== Standard de la programmation réactive +== Standard de la programmation réactive -Les standards de la programmation réactive sont basés sur deux modèles. +Les standards de la programmation réactive sont basés sur deux modèles{nbsp}: - ReactiveX: ReactiveX à été conçu pour fournir une API unifiée pour le traitement de collections asynchrones, en s'inspirant des méthodes des collections synchrones (comme map, filter, reduce). Il est souvent utilisé pour gérer des événements utilisateur, des requêtes réseau, et d'autres opérations asynchrones dans des applications interactives. Ces implémentations connues sont : RxJava et RxJs. +* _ReactiveX: ReactiveX à été conçu pour fournir une API unifiée pour le traitement de collections asynchrones, en s'inspirant des méthodes des collections synchrones (comme map, filter, reduce). Il est souvent utilisé pour gérer des événements utilisateur, des requêtes réseau, et d'autres opérations asynchrones dans des applications interactives. Ces implémentations connues sont : RxJava et RxJs. - Reactive Streams: Reactive Streams a été créé pour résoudre des problèmes spécifiques de backpressure dans les systèmes de traitement de données asynchrones, en définissant un ensemble minimal d'interfaces pour garantir une gestion cohérente et efficace des flux de données entre différentes bibliothèques réactives dans l'écosystème JVM. Ces implementation connues sont Akka Reactor Vertex et RxJAVA2 +* _Reactive Streams: Reactive Streams a été créé pour résoudre des problèmes spécifiques de backpressure dans les systèmes de traitement de données asynchrones, en définissant un ensemble minimal d'interfaces pour garantir une gestion cohérente et efficace des flux de données entre différentes bibliothèques réactives dans l'écosystème JVM. Ces implementation connues sont Akka Reactor Vertex et RxJAVA2 Dans notre article, on va s'intéresser à Reactor qui est une implémentation de Reactive streams. From 40f8bcba9f63ed00305cd1705abc4ea499e2a25f Mon Sep 17 00:00:00 2001 From: khairi Date: Wed, 27 Nov 2024 21:40:46 +0100 Subject: [PATCH 08/23] modify design article --- _posts/2024-11-23-programation-reactive.adoc | 28 ++++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc index f769c61c..0d100f19 100644 --- a/_posts/2024-11-23-programation-reactive.adoc +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -34,11 +34,11 @@ Pour surmonter ces limitations, les systèmes réactifs offrent une alternative Les principes de la programmation réactive sont encapsulés dans le "Manifeste Réactif", qui énonce quatre caractéristiques clés{nbsp}: -* _Responsive (Réactif) : Les systèmes réactifs répondent rapidement aux utilisateurs pour garantir une expérience fluide et interactive. +* Responsive (Réactif) : Les systèmes réactifs répondent rapidement aux utilisateurs pour garantir une expérience fluide et interactive. -* _Resilient (Résilient) : Les systèmes réactifs restent opérationnels même en cas de défaillance, grâce à des mécanismes de gestion des erreurs et de redondance. +* Resilient (Résilient) : Les systèmes réactifs restent opérationnels même en cas de défaillance, grâce à des mécanismes de gestion des erreurs et de redondance. -* _Elastic (Élastique) : Les systèmes réactifs s'adaptent aux variations de la charge de travail en allouant dynamiquement les ressources nécessaires. +* Elastic (Élastique) : Les systèmes réactifs s'adaptent aux variations de la charge de travail en allouant dynamiquement les ressources nécessaires. Message-Driven (Basé sur les Messages) : @@ -48,29 +48,29 @@ Les systèmes réactifs communiquent par la transmission de messages asynchrones Les standards de la programmation réactive sont basés sur deux modèles{nbsp}: -* _ReactiveX: ReactiveX à été conçu pour fournir une API unifiée pour le traitement de collections asynchrones, en s'inspirant des méthodes des collections synchrones (comme map, filter, reduce). Il est souvent utilisé pour gérer des événements utilisateur, des requêtes réseau, et d'autres opérations asynchrones dans des applications interactives. Ces implémentations connues sont : RxJava et RxJs. +* ReactiveX: ReactiveX à été conçu pour fournir une API unifiée pour le traitement de collections asynchrones, en s'inspirant des méthodes des collections synchrones (comme map, filter, reduce). Il est souvent utilisé pour gérer des événements utilisateur, des requêtes réseau, et d'autres opérations asynchrones dans des applications interactives. Ces implémentations connues sont : RxJava et RxJs. -* _Reactive Streams: Reactive Streams a été créé pour résoudre des problèmes spécifiques de backpressure dans les systèmes de traitement de données asynchrones, en définissant un ensemble minimal d'interfaces pour garantir une gestion cohérente et efficace des flux de données entre différentes bibliothèques réactives dans l'écosystème JVM. Ces implementation connues sont Akka Reactor Vertex et RxJAVA2 +* Reactive Streams: Reactive Streams a été créé pour résoudre des problèmes spécifiques de backpressure dans les systèmes de traitement de données asynchrones, en définissant un ensemble minimal d'interfaces pour garantir une gestion cohérente et efficace des flux de données entre différentes bibliothèques réactives dans l'écosystème JVM. Ces implementation connues sont Akka Reactor Vertex et RxJAVA2 Dans notre article, on va s'intéresser à Reactor qui est une implémentation de Reactive streams. -Les objectifs principaux de Reactive Streams sont : +Les objectifs principaux de Reactive Streams sont {nbsp}: -Asynchronisme : Gérer les flux de données de manière non bloquante et asynchrone. +* Asynchronisme : Gérer les flux de données de manière non bloquante et asynchrone. -Backpressure : Introduire une rétropression pour permettre aux consommateurs de signaler aux producteurs leur capacité à traiter les données, évitant ainsi les surcharges. +* Backpressure : Introduire une rétropression pour permettre aux consommateurs de signaler aux producteurs leur capacité à traiter les données, évitant ainsi les surcharges. -Interopérabilité : Fournir une interface standard pour que différentes bibliothèques réactives puissent fonctionner ensemble. +* Interopérabilité : Fournir une interface standard pour que différentes bibliothèques réactives puissent fonctionner ensemble. -Interfaces principales de Reactive Streams : +Interfaces principales de Reactive Streams {nbsp}: -Publisher : Représente une source qui peut émettre une séquence de valeurs asynchrones. Les éditeurs appellent la méthode subscribe() pour permettre aux abonnés de recevoir les éléments. +* Publisher : Représente une source qui peut émettre une séquence de valeurs asynchrones. Les éditeurs appellent la méthode subscribe() pour permettre aux abonnés de recevoir les éléments. -Subscriber : Représente un consommateur de données. Il reçoit les éléments émis par un Publisher via quatre méthodes : onSubscribe(), onNext(), onError(), et onComplete(). +* Subscriber : Représente un consommateur de données. Il reçoit les éléments émis par un Publisher via quatre méthodes : onSubscribe(), onNext(), onError(), et onComplete(). -Subscription : Gère le lien entre un Publisher et un Subscriber. Elle permet de demander des éléments (request(long n)) ou d'annuler la souscription (cancel()). +* Subscription : Gère le lien entre un Publisher et un Subscriber. Elle permet de demander des éléments (request(long n)) ou d'annuler la souscription (cancel()). -Processor : Combine les fonctionnalités d'un Publisher et d'un Subscriber. Un Processor reçoit des éléments, les traite, et les renvoie sous forme d'un autre flux. +* Processor : Combine les fonctionnalités d'un Publisher et d'un Subscriber. Un Processor reçoit des éléments, les traite, et les renvoie sous forme d'un autre flux. == Project Reactor : From ea0822ce3d3ab93f40b4948c24f944981300c129 Mon Sep 17 00:00:00 2001 From: khairi Date: Wed, 27 Nov 2024 21:44:31 +0100 Subject: [PATCH 09/23] modify design article --- _posts/2024-11-23-programation-reactive.adoc | 34 +++++++++----------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc index 0d100f19..4f615217 100644 --- a/_posts/2024-11-23-programation-reactive.adoc +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -40,9 +40,7 @@ Les principes de la programmation réactive sont encapsulés dans le "Manifeste * Elastic (Élastique) : Les systèmes réactifs s'adaptent aux variations de la charge de travail en allouant dynamiquement les ressources nécessaires. -Message-Driven (Basé sur les Messages) : - -Les systèmes réactifs communiquent par la transmission de messages asynchrones, facilitant la déconnexion et le découplage des composants. +* Message-Driven (Basé sur les Messages) : Les systèmes réactifs communiquent par la transmission de messages asynchrones, facilitant la déconnexion et le découplage des composants. == Standard de la programmation réactive @@ -76,41 +74,41 @@ Interfaces principales de Reactive Streams {nbsp}: Reactor est une bibliothèque réactive pour Java développée par Pivotal (maintenant VMware) et intégrée dans l'écosystème Spring. Elle fournit une implémentation de Reactive Streams et permet de construire des applications non bloquantes, asynchrones, et scalables. Reactor est au cœur de Spring WebFlux, le module réactif de Spring Framework. -Les principales abstractions fournies par Reactor sont : +Les principales abstractions fournies par Reactor sont {nbsp}: -=== Mono : Représente un flux réactif qui produit au maximum une seule valeur ou une erreur. + * Mono : Représente un flux réactif qui produit au maximum une seule valeur ou une erreur. -=== Flux : Représente un flux réactif qui peut émettre zéro, une ou plusieurs valeurs, voire un flux infini. + * Flux : Représente un flux réactif qui peut émettre zéro, une ou plusieurs valeurs, voire un flux infini. Ces deux types sont les composants de base utilisés pour modéliser des flux de données asynchrones en Java avec Reactor. -En pratique un Flux peut être sérialisé sous plusieur formes +En pratique un Flux peut être sérialisé sous plusieur formes {nbsp}: --Json Array : retourne un arrayList normale +* Json Array : retourne un arrayList normale --Text Event Stream : envoie un flux d'objets Json contenue donnés par donne dès qu’ils sont disponible. +* Text Event Stream : envoie un flux d'objets Json contenue donnés par donne dès qu’ils sont disponible. --Flux de json stream : De la même manière entre deux serveurs on peut avoir un flux de json Stream. +* Flux de json stream : De la même manière entre deux serveurs on peut avoir un flux de json Stream. == Spring Web Flux avec Reactor Spring web flux fait partie de projet Spring 5 c'est un module Spring basé sur une api http exposé à la source sur reactive Streams. dans lequel on continue à utiliser les mêmes annotation du contrôleurs Spring MVC (@conttreler, @RequestMapping, etc.) sauf que au lieu d'utiliser des type de retour List, T ou void, on utilise Flux ou Mono. -=== Composants de Spring WebFlux +=== Composants de Spring WebFlux {nbsp}: --Contrôleurs Réactifs : Comme dans Spring MVC, mais avec des types réactifs comme Mono et Flux. +* Contrôleurs Réactifs : Comme dans Spring MVC, mais avec des types réactifs comme Mono et Flux. --WebClient : Un client HTTP non-bloquant qui remplace RestTemplate pour les appels externes réactifs. +* WebClient : Un client HTTP non-bloquant qui remplace RestTemplate pour les appels externes réactifs. -R-outer Function : Une approche fonctionnelle pour définir des routes HTTP. +* Router Function : Une approche fonctionnelle pour définir des routes HTTP. -==== Avantages: +==== Avantages{nbsp}: -Scalabilité : La nature non-bloquante permet de gérer un grand nombre de connexions simultanées avec moins de threads. +* Scalabilité : La nature non-bloquante permet de gérer un grand nombre de connexions simultanées avec moins de threads. -Performance : Idéal pour les applications nécessitant une faible latence et une haute performance. +* Performance : Idéal pour les applications nécessitant une faible latence et une haute performance. -Flexibilité : Peut être utilisé pour des microservices, des applications Web, ou même des applications fonctionnant avec d'autres paradigmes réactifs comme RxJava. +* Flexibilité : Peut être utilisé pour des microservices, des applications Web, ou même des applications fonctionnant avec d'autres paradigmes réactifs comme RxJava. Configuration d'un projet Spring WebFlux From 2e62e3bd12ff6d6afc3b573810b25e2ebda46bc2 Mon Sep 17 00:00:00 2001 From: khairi Date: Wed, 27 Nov 2024 21:46:20 +0100 Subject: [PATCH 10/23] modify design article --- _posts/2024-11-23-programation-reactive.adoc | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc index 4f615217..79ad831e 100644 --- a/_posts/2024-11-23-programation-reactive.adoc +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -13,20 +13,18 @@ Avant d'explorer la programmation réactive, il est utile de comprendre les systèmes non réactifs traditionnels et leurs inconvénients, en particulier en ce qui concerne l'utilisation des ressources et la gestion des événements. -Les systèmes non réactifs, aussi appelés systèmes synchrones ou bloquants, sont les approches traditionnelles utilisées dans la programmation. Voici quelques caractéristiques clés: +Les systèmes non réactifs, aussi appelés systèmes synchrones ou bloquants, sont les approches traditionnelles utilisées dans la programmation. Voici quelques caractéristiques clés{nbsp}: -Traitement séquentiel Une tâche doit généralement attendre la fin de l'exécution de la tâche précédente avant de commencer, +* Traitement séquentiel Une tâche doit généralement attendre la fin de l'exécution de la tâche précédente avant de commencer, -Blocage des ressources : Les systèmes non réactifs bloquent souvent des ressources (comme des threads ou des connexions réseau) en attendant des résultats, +* Blocage des ressources : Les systèmes non réactifs bloquent souvent des ressources (comme des threads ou des connexions réseau) en attendant des résultats, -Gestion des événements complexes : La gestion des événements dans les systèmes non réactifs peut devenir complexe et difficile à maintenir, surtout lorsque le nombre d'événements augmente +* Gestion des événements complexes : La gestion des événements dans les systèmes non réactifs peut devenir complexe et difficile à maintenir, surtout lorsque le nombre d'événements augmente -Latence élevée : En raison de la nature bloquante de ces systèmes, ils peuvent entraîner une latence élevée, surtout dans les applications où la rapidité de réponse est cruciale. +* Latence élevée : En raison de la nature bloquante de ces systèmes, ils peuvent entraîner une latence élevée, surtout dans les applications où la rapidité de réponse est cruciale. -Scalabilité limitée : Comme chaque requête ou tâche peut nécessiter son propre thread ou processus, l'augmentation du nombre de requêtes peut rapidement saturer les ressources du système - - +* Scalabilité limitée : Comme chaque requête ou tâche peut nécessiter son propre thread ou processus, l'augmentation du nombre de requêtes peut rapidement saturer les ressources du système Pour surmonter ces limitations, les systèmes réactifs offrent une alternative en se concentrant sur l'asynchronisme, la non-bloquante, et l'efficacité dans l'utilisation des ressources. Ils permettent de créer des applications qui sont plus réactives, plus résilientes, et plus scalables, en répondant efficacement aux événements et en utilisant les ressources de manière optimale. From a66f3870a79acfed85166405565f472e94ecf135 Mon Sep 17 00:00:00 2001 From: khairi Date: Wed, 27 Nov 2024 21:55:49 +0100 Subject: [PATCH 11/23] modify introduction --- _posts/2024-11-23-programation-reactive.adoc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc index 79ad831e..e5dbe18d 100644 --- a/_posts/2024-11-23-programation-reactive.adoc +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -11,7 +11,9 @@ == Introduction: -Avant d'explorer la programmation réactive, il est utile de comprendre les systèmes non réactifs traditionnels et leurs inconvénients, en particulier en ce qui concerne l'utilisation des ressources et la gestion des événements. +Pendant longtemps, la programmation Java a été dominée par un modèle synchrone et bloquant. Cependant, l'évolution des architectures logicielles, notamment l'émergence des microservices et du cloud computing, a mis en évidence les limites de ce modèle. Pour répondre à ces nouveaux défis, un nouveau paradigme a vu le jour : la programmation réactive en s'appuyant sur le Reactive Manifesto, offre une solution robuste et performante pour mettre en œuvre des applications réactives en Java. + +Pour explorer la programmation réactive, il est utile de comprendre les systèmes non réactifs traditionnels et leurs inconvénients, en particulier en ce qui concerne l'utilisation des ressources et la gestion des événements. Les systèmes non réactifs, aussi appelés systèmes synchrones ou bloquants, sont les approches traditionnelles utilisées dans la programmation. Voici quelques caractéristiques clés{nbsp}: From de6289a08a91a6c05649f642f57b7b84731d2eff Mon Sep 17 00:00:00 2001 From: khairi Date: Wed, 27 Nov 2024 22:06:21 +0100 Subject: [PATCH 12/23] modify design article --- _posts/2024-11-23-programation-reactive.adoc | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc index e5dbe18d..092d3681 100644 --- a/_posts/2024-11-23-programation-reactive.adoc +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -140,15 +140,12 @@ Pour configurer un projet Maven avec Spring WebFlux et Reactor, il est essentiel @GetMapping("/hello") public Mono sayHello() { return Mono.just("Hello, WebFlux!"); - } ----- + } -[source,java] ----- -@GetMapping("/numbers") - public Flux getNumbers() { - return Flux.range(1, 10) .delayElements(Duration.ofMillis(100)); - } + @GetMapping("/numbers") + public Flux getNumbers() { + return Flux.range(1, 10) .delayElements(Duration.ofMillis(100)); + } } ---- From eebacdab35cd217882178e942b5c6f62cb7160eb Mon Sep 17 00:00:00 2001 From: khairi Date: Thu, 28 Nov 2024 20:44:06 +0100 Subject: [PATCH 13/23] add tags for article and add many suggestions --- _data/authors.yml | 11 ++- _posts/2024-11-23-programation-reactive.adoc | 70 +++++++++++--------- 2 files changed, 45 insertions(+), 36 deletions(-) diff --git a/_data/authors.yml b/_data/authors.yml index 63b17fc3..e5d9ae1b 100644 --- a/_data/authors.yml +++ b/_data/authors.yml @@ -259,13 +259,12 @@ khairikhadhraoui: name: "Khairi Khadhraoui" bio: "Diplômé en 2015 d’un diplôme d’ingénieur en spécialité système d’information à l’école polytechnique centrale de Tunis. -Khairi a travaillé sur plusieurs projets au cours de ces dernier 8 ans principalement dans le secteur de télécommunication, bancaire et finance +Khairi a travaillé sur plusieurs projets au cours de ces derniers 8 ans principalement dans le secteur des télécommunications, bancaire et financier. +Khairi est passionné par les nouvelles technologiques spécialement le développement d'applications web. -Khairi est passionné par les nouvelles technologiques spécialement au développement des application web. - -Ces centres d’intérêt se tourne principalement sur les randonné, les voyage et tous ce qui est lié à la nature." +Ces centres d’intérêt se tournent principalement sur les randonnés, les voyages et tous ce qui est lié à la nature." job: "Consultant Technique Senior" pagesciam: "https://www.sciam.fr/equipe/khairi-khadhraoui" - picture: khairikhadfhraoui.jpg + picture: khairikhadhraoui.jpg socials: - linkedin: "https://www.linkedin.com/in/khadhraoui-khairi-21940084/" \ No newline at end of file + linkedin: "khadhraoui-khairi-21940084/" \ No newline at end of file diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc index 092d3681..fc3e7f67 100644 --- a/_posts/2024-11-23-programation-reactive.adoc +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -1,36 +1,41 @@ -= La programmation réactive avec Reactor Spring web Flux += La programmation réactive avec Reactor et Spring Web Flux :showtitle: -:page-navtitle: La programmation réactive avec Reactor Spring web Flux -:page-excerpt: +:page-navtitle: La programmation réactive avec Reactor et Spring Web Flux +:page-excerpt: ce article decrit les notion de la programation non bloquante avec Reactor et spring Web Flux :layout: post :author: khairikhadhraoui -:page-tags: +:page-tags: [java, Spring webFlux, reactor, reactive programming, programation non bloquante, ReactiveX, Reactive Streams ] :page-vignette: programation-reactive.jpg :page-liquid: :page-categories: software news -== Introduction: +== Introduction -Pendant longtemps, la programmation Java a été dominée par un modèle synchrone et bloquant. Cependant, l'évolution des architectures logicielles, notamment l'émergence des microservices et du cloud computing, a mis en évidence les limites de ce modèle. Pour répondre à ces nouveaux défis, un nouveau paradigme a vu le jour : la programmation réactive en s'appuyant sur le Reactive Manifesto, offre une solution robuste et performante pour mettre en œuvre des applications réactives en Java. +Pendant longtemps, la programmation Java a été dominée par un modèle synchrone et bloquant. Cependant, l'évolution des architectures +logicielles, notamment l'émergence des microservices et du cloud computing, a mis en évidence les limites de ce modèle. Pour répondre +à ces nouveaux défis, un nouveau paradigme a vu le jour : la programmation réactive en s'appuyant sur le Reactive Manifesto, offre une +solution robuste et performante pour mettre en œuvre des applications réactives en Java. -Pour explorer la programmation réactive, il est utile de comprendre les systèmes non réactifs traditionnels et leurs inconvénients, en particulier en ce qui concerne l'utilisation des ressources et la gestion des événements. +Pour explorer la programmation réactive, il est utile de comprendre les systèmes non réactifs traditionnels et leurs inconvénients, +en particulier en ce qui concerne l'utilisation des ressources et la gestion des événements. -Les systèmes non réactifs, aussi appelés systèmes synchrones ou bloquants, sont les approches traditionnelles utilisées dans la programmation. Voici quelques caractéristiques clés{nbsp}: +Les systèmes non réactifs, aussi appelés systèmes synchrones ou bloquants, sont les approches traditionnelles utilisées dans la +programmation. Voici quelques caractéristiques clés{nbsp}: -* Traitement séquentiel Une tâche doit généralement attendre la fin de l'exécution de la tâche précédente avant de commencer, +* Traitement séquentiel : une tâche doit généralement attendre la fin de l'exécution de la tâche précédente avant de commencer, -* Blocage des ressources : Les systèmes non réactifs bloquent souvent des ressources (comme des threads ou des connexions réseau) en attendant des résultats, +* Blocage des ressources : les systèmes non réactifs bloquent souvent des ressources (comme des threads ou des connexions réseau) en attendant des résultats, -* Gestion des événements complexes : La gestion des événements dans les systèmes non réactifs peut devenir complexe et difficile à maintenir, surtout lorsque le nombre d'événements augmente +* Gestion des événements complexes : la gestion des événements dans les systèmes non réactifs peut devenir complexe et difficile à maintenir, surtout lorsque le nombre d'événements augmente -* Latence élevée : En raison de la nature bloquante de ces systèmes, ils peuvent entraîner une latence élevée, surtout dans les applications où la rapidité de réponse est cruciale. +* Latence élevée : en raison de la nature bloquante de ces systèmes, ils peuvent entraîner une latence élevée, surtout dans les applications où la rapidité de réponse est cruciale -* Scalabilité limitée : Comme chaque requête ou tâche peut nécessiter son propre thread ou processus, l'augmentation du nombre de requêtes peut rapidement saturer les ressources du système +* Scalabilité limitée : comme chaque requête ou tâche peut nécessiter son propre thread ou processus, l'augmentation du nombre de requêtes peut rapidement saturer les ressources du système Pour surmonter ces limitations, les systèmes réactifs offrent une alternative en se concentrant sur l'asynchronisme, la non-bloquante, et l'efficacité dans l'utilisation des ressources. Ils permettent de créer des applications qui sont plus réactives, plus résilientes, et plus scalables, en répondant efficacement aux événements et en utilisant les ressources de manière optimale. -== Principes programmation réactive +== Les principes de la programmation réactive Les principes de la programmation réactive sont encapsulés dans le "Manifeste Réactif", qui énonce quatre caractéristiques clés{nbsp}: @@ -44,25 +49,29 @@ Les principes de la programmation réactive sont encapsulés dans le "Manifeste == Standard de la programmation réactive -Les standards de la programmation réactive sont basés sur deux modèles{nbsp}: +Les bibliotheques de la programmation réactive sont basés sur deux modèles{nbsp}: -* ReactiveX: ReactiveX à été conçu pour fournir une API unifiée pour le traitement de collections asynchrones, en s'inspirant des méthodes des collections synchrones (comme map, filter, reduce). Il est souvent utilisé pour gérer des événements utilisateur, des requêtes réseau, et d'autres opérations asynchrones dans des applications interactives. Ces implémentations connues sont : RxJava et RxJs. +* ReactiveX : ReactiveX a été conçu pour fournir une API unifiée pour le traitement de collections asynchrones, en s'inspirant des méthodes +des collections synchrones (comme map, filter, reduce). Il est souvent utilisé pour gérer des événements utilisateur, des requêtes +réseau, et d'autres opérations asynchrones dans des applications interactives. Ces implémentations connues sont : RxJava et RxJs. -* Reactive Streams: Reactive Streams a été créé pour résoudre des problèmes spécifiques de backpressure dans les systèmes de traitement de données asynchrones, en définissant un ensemble minimal d'interfaces pour garantir une gestion cohérente et efficace des flux de données entre différentes bibliothèques réactives dans l'écosystème JVM. Ces implementation connues sont Akka Reactor Vertex et RxJAVA2 +* Reactive Streams: Reactive Streams a été créé pour résoudre des problèmes spécifiques de backpressure dans les systèmes de traitement de données +asynchrones, en définissant un ensemble minimal d'interfaces pour garantir une gestion cohérente et efficace des flux de données +entre différentes bibliothèques réactives dans l'écosystème JVM. Ces implementation connues sont Akka Reactor Vertex et RxJAVA2 Dans notre article, on va s'intéresser à Reactor qui est une implémentation de Reactive streams. Les objectifs principaux de Reactive Streams sont {nbsp}: -* Asynchronisme : Gérer les flux de données de manière non bloquante et asynchrone. +* Asynchronisme : gérer les flux de données de manière non bloquante et asynchrone. -* Backpressure : Introduire une rétropression pour permettre aux consommateurs de signaler aux producteurs leur capacité à traiter les données, évitant ainsi les surcharges. +* Backpressure :S'assurer du nombre d'éléments que le consommateur peut recevoir, évitant ainsi les surcharges. * Interopérabilité : Fournir une interface standard pour que différentes bibliothèques réactives puissent fonctionner ensemble. -Interfaces principales de Reactive Streams {nbsp}: +Les principales interfaces de Reactive Streams sont{nbsp}: -* Publisher : Représente une source qui peut émettre une séquence de valeurs asynchrones. Les éditeurs appellent la méthode subscribe() pour permettre aux abonnés de recevoir les éléments. +* `Publisher` : représente une source qui peut émettre une séquence de valeurs asynchrones. Les éditeurs appellent la méthode `subscribe()` pour permettre aux abonnés de recevoir les éléments. * Subscriber : Représente un consommateur de données. Il reçoit les éléments émis par un Publisher via quatre méthodes : onSubscribe(), onNext(), onError(), et onComplete(). @@ -162,22 +171,23 @@ public class WebClientExample { } ---- -=== Gestion du Backpressure +=== La gestion du backpressure -Le backpressure est une composante essentielle dans les systèmes réactifs pour gérer le flux de données entre les producteurs et les consommateurs. Avec Reactor, vous pouvez contrôler le backpressure via des opérateurs comme limitRate. +Le backpressure est une composante essentielle dans les systèmes réactifs pour gérer le flux de données entre les producteurs et les consommateurs. +Avec Reactor, vous pouvez contrôler le backpressure via des opérateurs comme `limitRate`. -Exemple d'utilisation de limitRate pour réguler la consommation des données : +Exemple d'utilisation de `limitRate` pour réguler la consommation des données : [source,java] ---- Flux flux = WebClient.create("http://example.com") - .get() - .uri("/api/large-stream") - .retrieve() .bodyToFlux(Integer.class) - .limitRate(5); - flux.subscribe(data -> { // Traitement des données - System.out.println("Received: " + data); + .get() + .uri("/api/large-stream") + .retrieve() .bodyToFlux(Integer.class) + .limitRate(5); + flux.subscribe(data -> { // Traitement des données + System.out.println("Received: " + data); }); ---- From f6b15cb0010da8f68c9c8ff8bcc645b4cbfa81ce Mon Sep 17 00:00:00 2001 From: khairi Date: Fri, 29 Nov 2024 21:53:35 +0100 Subject: [PATCH 14/23] =?UTF-8?q?ajout=20inconv=C3=A9nients=20et=20modifie?= =?UTF-8?q?r=20conclusion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _posts/2024-11-23-programation-reactive.adoc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc index fc3e7f67..24992578 100644 --- a/_posts/2024-11-23-programation-reactive.adoc +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -194,6 +194,9 @@ Flux flux = WebClient.create("http://example.com") == Conclusion -Spring Reactor propulse le développement d'applications modernes vers de nouveaux sommets en leur conférant réactivité, performance et résilience. En s'alignant sur le Reactive Manifesto, cette technologie ouvre la voie à des systèmes distribués agiles et efficaces. Toutefois, son adoption requiert une solide compréhension des concepts fondamentaux et une évaluation minutieuse des besoins spécifiques de chaque projet. +Spring Reactor propulse le développement d'applications modernes vers de nouveaux sommets en leur conférant réactivité, performance et résilience. En s'alignant +sur le Reactive Manifesto, cette technologie ouvre la voie à des systèmes distribués agiles et efficaces. Toutefois, son adoption requiert une solide + compréhension des concepts fondamentaux et une évaluation minutieuse des besoins spécifiques de chaque projet. -Face à l'évolution rapide des architectures modernes (cloud, microservices, événements), la programmation réactive s'impose comme une approche incontournable. Il est passionnant d'envisager les prochaines avancées dans ce domaine et d'imaginer les nouveaux outils qui transformeront encore davantage notre façon de concevoir des systèmes réactifs. \ No newline at end of file +L'adoption de WebFlux implique une courbe d'apprentissage plus prononcée, en particulier pour comprendre les concepts de la programmation réactive. Cependant, +pour les projets exigeant une grande performance et une grande évolutivité, WebFlux est une solution robuste et adaptée aux besoins actuels. From e29317a768f5173c81c02eb3f3ce3b72fcf2596f Mon Sep 17 00:00:00 2001 From: khairi Date: Fri, 29 Nov 2024 21:57:07 +0100 Subject: [PATCH 15/23] indentation code --- _posts/2024-11-23-programation-reactive.adoc | 38 +++++++++++--------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc index 24992578..01d1092f 100644 --- a/_posts/2024-11-23-programation-reactive.adoc +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -47,9 +47,7 @@ Les principes de la programmation réactive sont encapsulés dans le "Manifeste * Message-Driven (Basé sur les Messages) : Les systèmes réactifs communiquent par la transmission de messages asynchrones, facilitant la déconnexion et le découplage des composants. -== Standard de la programmation réactive - -Les bibliotheques de la programmation réactive sont basés sur deux modèles{nbsp}: +== Les bibliotheques de la programmation réactive sont basés sur deux modèles{nbsp}: * ReactiveX : ReactiveX a été conçu pour fournir une API unifiée pour le traitement de collections asynchrones, en s'inspirant des méthodes des collections synchrones (comme map, filter, reduce). Il est souvent utilisé pour gérer des événements utilisateur, des requêtes @@ -119,7 +117,19 @@ Spring web flux fait partie de projet Spring 5 c'est un module Spring basé sur * Flexibilité : Peut être utilisé pour des microservices, des applications Web, ou même des applications fonctionnant avec d'autres paradigmes réactifs comme RxJava. -Configuration d'un projet Spring WebFlux +==== Inconvénients + +Bien que la programmation réactive soit un outil puissant pour de nombreuses applications modernes, elle présente également des inconvénients. + +* Débogage et test complexes : Les applications réactives introduisent des comportements asynchrones difficiles à tracer, rendant le débogage et la compréhension des erreurs plus compliqués. De même, les tests nécessitent souvent des outils spécialisés pour simuler les flux asynchrones. + +* Code plus difficile à lire et maintenir : En raison de la composition des flux et des chaînes d'opérateurs, le code réactif peut devenir difficile à comprendre, en particulier pour ceux qui n’ont pas l’habitude de travailler avec ce paradigme. + +* Coût d'intégration dans les projets existants : Migrer une application traditionnelle vers une approche réactive peut être coûteux et complexe. Il peut être nécessaire de refactoriser une grande partie du code et d’adapter les couches d’infrastructure. + +* Pas toujours adapté : Toutes les applications n'ont pas besoin des avantages de la programmation réactive, comme la haute disponibilité ou l'évolutivité massive. Pour des applications simples ou à faible trafic, l'approche réactive peut introduire une complexité inutile. + += Configuration d'un projet Spring WebFlux == Configuration Maven : @@ -153,7 +163,7 @@ Pour configurer un projet Maven avec Spring WebFlux et Reactor, il est essentiel @GetMapping("/numbers") public Flux getNumbers() { - return Flux.range(1, 10) .delayElements(Duration.ofMillis(100)); + return Flux.range(1, 10).delayElements(Duration.ofMillis(100)); } } ---- @@ -183,20 +193,16 @@ Exemple d'utilisation de `limitRate` pour réguler la consommation des données Flux flux = WebClient.create("http://example.com") .get() - .uri("/api/large-stream") - .retrieve() .bodyToFlux(Integer.class) - .limitRate(5); - flux.subscribe(data -> { // Traitement des données - System.out.println("Received: " + data); -}); + .uri("/api/large-stream") + .retrieve() .bodyToFlux(Integer.class) + .limitRate(5); + flux.subscribe(data -> { System.out.println("Received: " + data);}); ---- == Conclusion Spring Reactor propulse le développement d'applications modernes vers de nouveaux sommets en leur conférant réactivité, performance et résilience. En s'alignant -sur le Reactive Manifesto, cette technologie ouvre la voie à des systèmes distribués agiles et efficaces. Toutefois, son adoption requiert une solide - compréhension des concepts fondamentaux et une évaluation minutieuse des besoins spécifiques de chaque projet. - -L'adoption de WebFlux implique une courbe d'apprentissage plus prononcée, en particulier pour comprendre les concepts de la programmation réactive. Cependant, -pour les projets exigeant une grande performance et une grande évolutivité, WebFlux est une solution robuste et adaptée aux besoins actuels. +sur le Reactive Manifesto, cette technologie ouvre la voie à des systèmes distribués agiles et efficaces. Toutefois, son adoption implique une courbe d'apprentissage +plus prononcée, en particulier pour comprendre les concepts de la programmation réactive. Cependant, pour les projets exigeant une grande performance et une grande +évolutivité, WebFlux est une solution robuste et adaptée aux besoins actuels. From 5af46517d22e7fb3265382f70fc5dfe41e944570 Mon Sep 17 00:00:00 2001 From: khairi Date: Fri, 29 Nov 2024 21:58:42 +0100 Subject: [PATCH 16/23] indentation code --- _posts/2024-11-23-programation-reactive.adoc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc index 01d1092f..c0e482cf 100644 --- a/_posts/2024-11-23-programation-reactive.adoc +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -117,7 +117,7 @@ Spring web flux fait partie de projet Spring 5 c'est un module Spring basé sur * Flexibilité : Peut être utilisé pour des microservices, des applications Web, ou même des applications fonctionnant avec d'autres paradigmes réactifs comme RxJava. -==== Inconvénients +==== Inconvénients : Bien que la programmation réactive soit un outil puissant pour de nombreuses applications modernes, elle présente également des inconvénients. @@ -129,9 +129,9 @@ Bien que la programmation réactive soit un outil puissant pour de nombreuses ap * Pas toujours adapté : Toutes les applications n'ont pas besoin des avantages de la programmation réactive, comme la haute disponibilité ou l'évolutivité massive. Pour des applications simples ou à faible trafic, l'approche réactive peut introduire une complexité inutile. -= Configuration d'un projet Spring WebFlux +== Configuration d'un projet Spring WebFlux -== Configuration Maven : +=== Configuration Maven : Pour configurer un projet Maven avec Spring WebFlux et Reactor, il est essentiel d'ajouter les dépendances appropriées dans le fichier pom.xml. Voici les étapes à suivre pour inclure ces dépendances. [source,plain] @@ -200,7 +200,7 @@ Flux flux = WebClient.create("http://example.com") ---- -== Conclusion += Conclusion Spring Reactor propulse le développement d'applications modernes vers de nouveaux sommets en leur conférant réactivité, performance et résilience. En s'alignant sur le Reactive Manifesto, cette technologie ouvre la voie à des systèmes distribués agiles et efficaces. Toutefois, son adoption implique une courbe d'apprentissage From b93b86c8501ce413672a9e312628dfda40b5d14a Mon Sep 17 00:00:00 2001 From: khairi Date: Fri, 29 Nov 2024 22:00:52 +0100 Subject: [PATCH 17/23] modify conclusion --- _posts/2024-11-23-programation-reactive.adoc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc index c0e482cf..75952238 100644 --- a/_posts/2024-11-23-programation-reactive.adoc +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -204,5 +204,4 @@ Flux flux = WebClient.create("http://example.com") Spring Reactor propulse le développement d'applications modernes vers de nouveaux sommets en leur conférant réactivité, performance et résilience. En s'alignant sur le Reactive Manifesto, cette technologie ouvre la voie à des systèmes distribués agiles et efficaces. Toutefois, son adoption implique une courbe d'apprentissage -plus prononcée, en particulier pour comprendre les concepts de la programmation réactive. Cependant, pour les projets exigeant une grande performance et une grande -évolutivité, WebFlux est une solution robuste et adaptée aux besoins actuels. +plus prononcée, en particulier pour comprendre les concepts de la programmation réactive. From e99a5ddb6c29c91296f3b7583ca8bc95e7c2da0d Mon Sep 17 00:00:00 2001 From: khairi Date: Fri, 29 Nov 2024 22:46:56 +0100 Subject: [PATCH 18/23] add suggestion --- _posts/2024-11-23-programation-reactive.adoc | 84 +++++++++++--------- 1 file changed, 48 insertions(+), 36 deletions(-) diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc index 75952238..277e3c99 100644 --- a/_posts/2024-11-23-programation-reactive.adoc +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -9,7 +9,7 @@ :page-liquid: :page-categories: software news -== Introduction +== Introduction : Pendant longtemps, la programmation Java a été dominée par un modèle synchrone et bloquant. Cependant, l'évolution des architectures logicielles, notamment l'émergence des microservices et du cloud computing, a mis en évidence les limites de ce modèle. Pour répondre @@ -33,19 +33,21 @@ programmation. Voici quelques caractéristiques clés{nbsp}: * Scalabilité limitée : comme chaque requête ou tâche peut nécessiter son propre thread ou processus, l'augmentation du nombre de requêtes peut rapidement saturer les ressources du système -Pour surmonter ces limitations, les systèmes réactifs offrent une alternative en se concentrant sur l'asynchronisme, la non-bloquante, et l'efficacité dans l'utilisation des ressources. Ils permettent de créer des applications qui sont plus réactives, plus résilientes, et plus scalables, en répondant efficacement aux événements et en utilisant les ressources de manière optimale. +Pour surmonter ces limitations, les systèmes réactifs offrent une alternative en se concentrant sur l'asynchronisme, non-bloquant, et l'efficacité dans l'utilisation +des ressources. Ils permettent de créer des applications qui sont plus réactives, plus résilientes, et plus scalables, en répondant efficacement aux événements et en + utilisant les ressources de manière optimale. == Les principes de la programmation réactive Les principes de la programmation réactive sont encapsulés dans le "Manifeste Réactif", qui énonce quatre caractéristiques clés{nbsp}: -* Responsive (Réactif) : Les systèmes réactifs répondent rapidement aux utilisateurs pour garantir une expérience fluide et interactive. +* Responsive (Réactif) : les systèmes réactifs répondent rapidement aux utilisateurs pour garantir une expérience fluide et interactive. -* Resilient (Résilient) : Les systèmes réactifs restent opérationnels même en cas de défaillance, grâce à des mécanismes de gestion des erreurs et de redondance. +* Resilient (Résilient) : les systèmes réactifs restent opérationnels même en cas de défaillance, grâce à des mécanismes de gestion des erreurs et de redondance. -* Elastic (Élastique) : Les systèmes réactifs s'adaptent aux variations de la charge de travail en allouant dynamiquement les ressources nécessaires. +* Elastic (Élastique) : les systèmes réactifs s'adaptent aux variations de la charge de travail en allouant dynamiquement les ressources nécessaires. -* Message-Driven (Basé sur les Messages) : Les systèmes réactifs communiquent par la transmission de messages asynchrones, facilitant la déconnexion et le découplage des composants. +* Message-Driven (Basé sur les Messages) : les systèmes réactifs communiquent par la transmission de messages asynchrones, facilitant la connexion et le découplage des composants. == Les bibliotheques de la programmation réactive sont basés sur deux modèles{nbsp}: @@ -53,11 +55,11 @@ Les principes de la programmation réactive sont encapsulés dans le "Manifeste des collections synchrones (comme map, filter, reduce). Il est souvent utilisé pour gérer des événements utilisateur, des requêtes réseau, et d'autres opérations asynchrones dans des applications interactives. Ces implémentations connues sont : RxJava et RxJs. -* Reactive Streams: Reactive Streams a été créé pour résoudre des problèmes spécifiques de backpressure dans les systèmes de traitement de données -asynchrones, en définissant un ensemble minimal d'interfaces pour garantir une gestion cohérente et efficace des flux de données -entre différentes bibliothèques réactives dans l'écosystème JVM. Ces implementation connues sont Akka Reactor Vertex et RxJAVA2 +* Reactive Streams : Reactive Streams a été créé pour résoudre des problèmes spécifiques de backpressure dans les systèmes de traitement + de données asynchrones, en définissant un ensemble minimal d'interfaces pour garantir une gestion cohérente et efficace des flux de données + entre différentes bibliothèques réactives dans l'écosystème JVM. Les implémentations connues sont Akka, Reactor, Vert.x et RxJAVA2. -Dans notre article, on va s'intéresser à Reactor qui est une implémentation de Reactive streams. +Dans cet article, on va s'intéresser à Reactor qui est une implémentation de Reactive streams. Les objectifs principaux de Reactive Streams sont {nbsp}: @@ -71,53 +73,56 @@ Les principales interfaces de Reactive Streams sont{nbsp}: * `Publisher` : représente une source qui peut émettre une séquence de valeurs asynchrones. Les éditeurs appellent la méthode `subscribe()` pour permettre aux abonnés de recevoir les éléments. -* Subscriber : Représente un consommateur de données. Il reçoit les éléments émis par un Publisher via quatre méthodes : onSubscribe(), onNext(), onError(), et onComplete(). +* `Subscriber` : représente un consommateur de données. Il reçoit les éléments émis par le producteur 'Publisher' via la méthode : onSubscribe(). -* Subscription : Gère le lien entre un Publisher et un Subscriber. Elle permet de demander des éléments (request(long n)) ou d'annuler la souscription (cancel()). +* `Subscription` : gère le lien entre un 'Publisher' et un 'Subscriber'. Elle permet de demander des éléments (request(long n)) ou d'annuler la souscription (cancel()). -* Processor : Combine les fonctionnalités d'un Publisher et d'un Subscriber. Un Processor reçoit des éléments, les traite, et les renvoie sous forme d'un autre flux. +* `Processor` : combine les fonctionnalités d'un 'Publisher' et d'un 'Subscriber'. Un 'Processor' reçoit des éléments, les traite, et les renvoie sous forme d'un autre flux. -== Project Reactor : +== Le Project Reactor : -Reactor est une bibliothèque réactive pour Java développée par Pivotal (maintenant VMware) et intégrée dans l'écosystème Spring. Elle fournit une implémentation de Reactive Streams et permet de construire des applications non bloquantes, asynchrones, et scalables. Reactor est au cœur de Spring WebFlux, le module réactif de Spring Framework. +Reactor est une bibliothèque réactive pour Java développée par Pivotal (maintenant VMware) et intégrée dans l'écosystème Spring. Elle fournit une implémentation de Reactive Streams et permet de +construire des applications non bloquantes, asynchrones, et scalables. Reactor est au cœur de Spring WebFlux, le module réactif Web de Spring Framework. Les principales abstractions fournies par Reactor sont {nbsp}: - * Mono : Représente un flux réactif qui produit au maximum une seule valeur ou une erreur. + * 'Mono' : représente un flux réactif qui produit au maximum une seule valeur. - * Flux : Représente un flux réactif qui peut émettre zéro, une ou plusieurs valeurs, voire un flux infini. + * 'Flux' : représente un flux réactif qui peut émettre zéro, une ou plusieurs valeurs, voire un flux infini. Ces deux types sont les composants de base utilisés pour modéliser des flux de données asynchrones en Java avec Reactor. -En pratique un Flux peut être sérialisé sous plusieur formes {nbsp}: +En pratique un 'Flux' peut être sérialisé sous plusieur formes{nbsp}: -* Json Array : retourne un arrayList normale +* Json Array -* Text Event Stream : envoie un flux d'objets Json contenue donnés par donne dès qu’ils sont disponible. +* Text Event Stream -* Flux de json stream : De la même manière entre deux serveurs on peut avoir un flux de json Stream. +* Flux de json stream == Spring Web Flux avec Reactor -Spring web flux fait partie de projet Spring 5 c'est un module Spring basé sur une api http exposé à la source sur reactive Streams. dans lequel on continue à utiliser les mêmes annotation du contrôleurs Spring MVC (@conttreler, @RequestMapping, etc.) sauf que au lieu d'utiliser des type de retour List, T ou void, on utilise Flux ou Mono. +Spring Web Flux fait partie de projet Spring 5 : c'est un module Spring basé sur une API HTTP exposée à la source sur reactive Streams dans lequel +on continue à utiliser les mêmes annotations pour les contrôleurs Spring MVC (`@Controller`, `@RequestMapping`, etc). Cependant au lieu d'utiliser +des types de retour `List`, `T` ou `void`, on utilise `Flux` ou `Mono`. -=== Composants de Spring WebFlux {nbsp}: +=== Les composants de Spring WebFlux {nbsp}: -* Contrôleurs Réactifs : Comme dans Spring MVC, mais avec des types réactifs comme Mono et Flux. +* Les contrôleurs réactifs : comme dans Spring MVC, mais avec des types réactifs `Mono` et `Flux`. -* WebClient : Un client HTTP non-bloquant qui remplace RestTemplate pour les appels externes réactifs. +* `WebClient` : un client HTTP non-bloquant qui remplace `RestTemplate` pour les appels externes réactifs. -* Router Function : Une approche fonctionnelle pour définir des routes HTTP. +* Router Function : une approche fonctionnelle pour définir des routes HTTP. -==== Avantages{nbsp}: +==== Les avantages{nbsp}: -* Scalabilité : La nature non-bloquante permet de gérer un grand nombre de connexions simultanées avec moins de threads. +* Scalabilité : la nature non-bloquante permet de gérer un grand nombre de connexions simultanées avec moins de threads. -* Performance : Idéal pour les applications nécessitant une faible latence et une haute performance. +* Performance : adapté pour les applications nécessitant une faible latence et une haute performance. -* Flexibilité : Peut être utilisé pour des microservices, des applications Web, ou même des applications fonctionnant avec d'autres paradigmes réactifs comme RxJava. +* Flexibilité : peut être utilisé pour des microservices, des applications Web, ou même des applications fonctionnant avec d'autres paradigmes réactifs comme RxJava. -==== Inconvénients : +==== Les inconvénients : Bien que la programmation réactive soit un outil puissant pour de nombreuses applications modernes, elle présente également des inconvénients. @@ -129,11 +134,11 @@ Bien que la programmation réactive soit un outil puissant pour de nombreuses ap * Pas toujours adapté : Toutes les applications n'ont pas besoin des avantages de la programmation réactive, comme la haute disponibilité ou l'évolutivité massive. Pour des applications simples ou à faible trafic, l'approche réactive peut introduire une complexité inutile. -== Configuration d'un projet Spring WebFlux +== La configuration d'un projet Spring WebFlux -=== Configuration Maven : +=== La configuration Maven : -Pour configurer un projet Maven avec Spring WebFlux et Reactor, il est essentiel d'ajouter les dépendances appropriées dans le fichier pom.xml. Voici les étapes à suivre pour inclure ces dépendances. +Pour configurer un projet Maven avec Spring WebFlux et Reactor, il faut ajouter les dépendances appropriées dans le fichier pom.xml : [source,plain] ---- @@ -148,8 +153,15 @@ Pour configurer un projet Maven avec Spring WebFlux et Reactor, il est essentiel ---- -=== Création d'un contrôleur réactif: +=== La création d'un contrôleur réactif : +Le contrôleur contient deux méthodes : + +*La première méthode : retourne un Mono créé à partir d'une valeur unique fournie en paramètre. + +*La deuxième méthode fournit un flux (Flux) représentant une séquence d'entiers allant de 1 à 10, avec un délai de 100 millisecondes entre chaque élément émis. + +Si un client appelle l'API /numbers, il recevra chaque nombre (de 1 à 10) avec un intervalle de 100 millisecondes entre eux. [source,java] ---- @@ -168,7 +180,7 @@ Pour configurer un projet Maven avec Spring WebFlux et Reactor, il est essentiel } ---- -=== Exemple d'utilisation de WebClient : +=== Un exemple d'utilisation de WebClient : [source,java] ---- From 7e3f80a49a53111d5f7247c00557e88583213290 Mon Sep 17 00:00:00 2001 From: khairi Date: Fri, 29 Nov 2024 22:54:59 +0100 Subject: [PATCH 19/23] modify introduction --- _posts/2024-11-23-programation-reactive.adoc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc index 277e3c99..2a3a452d 100644 --- a/_posts/2024-11-23-programation-reactive.adoc +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -11,10 +11,10 @@ == Introduction : -Pendant longtemps, la programmation Java a été dominée par un modèle synchrone et bloquant. Cependant, l'évolution des architectures -logicielles, notamment l'émergence des microservices et du cloud computing, a mis en évidence les limites de ce modèle. Pour répondre -à ces nouveaux défis, un nouveau paradigme a vu le jour : la programmation réactive en s'appuyant sur le Reactive Manifesto, offre une -solution robuste et performante pour mettre en œuvre des applications réactives en Java. +L'évolution rapide des architectures logicielles vers des modèles distribués (microservices) et cloud-native a révélé les contraintes +inhérentes à la programmation bloquante traditionnelle. Pour répondre à ces nouveaux défis, la programmation réactive, fondée sur les +principes du Reactive Manifesto, propose un paradigme plus adapté pour concevoir et développer des applications Java hautement réactives, +capables de s'adapter aux fluctuations de charge et de garantir une faible latence. Pour explorer la programmation réactive, il est utile de comprendre les systèmes non réactifs traditionnels et leurs inconvénients, en particulier en ce qui concerne l'utilisation des ressources et la gestion des événements. From 72d16c1ab737ec71fc6aa19953eed3a10be6de91 Mon Sep 17 00:00:00 2001 From: khairi Date: Fri, 29 Nov 2024 22:57:17 +0100 Subject: [PATCH 20/23] add suggestion --- _posts/2024-11-23-programation-reactive.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc index 2a3a452d..2e442965 100644 --- a/_posts/2024-11-23-programation-reactive.adoc +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -75,7 +75,7 @@ Les principales interfaces de Reactive Streams sont{nbsp}: * `Subscriber` : représente un consommateur de données. Il reçoit les éléments émis par le producteur 'Publisher' via la méthode : onSubscribe(). -* `Subscription` : gère le lien entre un 'Publisher' et un 'Subscriber'. Elle permet de demander des éléments (request(long n)) ou d'annuler la souscription (cancel()). +* `Subscription` : gère le lien entre un `Publisher` et un `Subscriber`. Elle permet de demander des éléments (`request(long n)`) ou d'annuler la souscription (`cancel()`). * `Processor` : combine les fonctionnalités d'un 'Publisher' et d'un 'Subscriber'. Un 'Processor' reçoit des éléments, les traite, et les renvoie sous forme d'un autre flux. From 667e85a0986806cc71ab5a2ed8d88c7b15998e36 Mon Sep 17 00:00:00 2001 From: khairi Date: Sun, 1 Dec 2024 20:31:24 +0100 Subject: [PATCH 21/23] add discription to code --- _posts/2024-11-23-programation-reactive.adoc | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc index 2e442965..c7898607 100644 --- a/_posts/2024-11-23-programation-reactive.adoc +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -155,7 +155,7 @@ Pour configurer un projet Maven avec Spring WebFlux et Reactor, il faut ajouter === La création d'un contrôleur réactif : -Le contrôleur contient deux méthodes : +Nous allons utiliser un contrôleur contient deux méthodes : *La première méthode : retourne un Mono créé à partir d'une valeur unique fournie en paramètre. @@ -182,12 +182,22 @@ Si un client appelle l'API /numbers, il recevra chaque nombre (de 1 à 10) avec === Un exemple d'utilisation de WebClient : +WebClient C'est une classe fournie par Spring WebFlux pour effectuer des appels HTTP non bloquants (client HTTP réactif). + +Nous allons initialiser un WebClient par la methode create("http://example.com") pointant vers l'URL de base http://example.com + +La méthode get() initie une requête HTTP de type GET, tandis que uri("/api/data") spécifie le chemin relatif de l'API +cible (ajouté à l'URL de base du WebClient). La méthode retrieve() exécute la requête et prépare la réponse pour être traitée. +Enfin, bodyToMono(String.class) extrait le corps de la réponse HTTP et le convertit en un objet réactif de type Mono, +permettant de manipuler la réponse asynchrone dans un pipeline réactif. Si la requête réussit, le contenu de la réponse sera +disponible sous forme de chaîne dans le Mono. + [source,java] ---- public class WebClientExample { private final WebClient webClient =WebClient.create("http://example.com"); public Mono fetchData() { - return webClient.get() .uri("/api/data") .retrieve() + return webClient.get().uri("/api/data") .retrieve() .bodyToMono(String.class); } } @@ -200,6 +210,10 @@ Avec Reactor, vous pouvez contrôler le backpressure via des opérateurs comme ` Exemple d'utilisation de `limitRate` pour réguler la consommation des données : +La methode limitRate(5) applique un mécanisme de contrôle du flux (backpressure) pour limiter la consommation à un maximum de 5 éléments à la fois. Enfin, +un abonné est attaché au flux avec subscribe(), qui imprime chaque élément reçu via un callback, permettant de traiter les données au fur et à mesure de leur +arrivée. Ce code est adapté au traitement de grandes quantités de données de manière asynchrone et contrôlée. + [source,java] ---- From 73964eb187e897b8d581624c11625ba70c75559c Mon Sep 17 00:00:00 2001 From: khairi Date: Thu, 5 Dec 2024 21:52:07 +0100 Subject: [PATCH 22/23] add suggestion --- _posts/2024-11-23-programation-reactive.adoc | 134 ++++++++++--------- 1 file changed, 74 insertions(+), 60 deletions(-) diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc index c7898607..5d901298 100644 --- a/_posts/2024-11-23-programation-reactive.adoc +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -1,37 +1,45 @@ = La programmation réactive avec Reactor et Spring Web Flux :showtitle: :page-navtitle: La programmation réactive avec Reactor et Spring Web Flux -:page-excerpt: ce article decrit les notion de la programation non bloquante avec Reactor et spring Web Flux +:page-excerpt: Cet article décrit les notions de la programmation non bloquante avec Reactor et Spring WebFlux. :layout: post :author: khairikhadhraoui :page-tags: [java, Spring webFlux, reactor, reactive programming, programation non bloquante, ReactiveX, Reactive Streams ] -:page-vignette: programation-reactive.jpg +:page-vignette: images/khairi/programation-reactive.jpg :page-liquid: :page-categories: software news -== Introduction : +== Introduction: L'évolution rapide des architectures logicielles vers des modèles distribués (microservices) et cloud-native a révélé les contraintes inhérentes à la programmation bloquante traditionnelle. Pour répondre à ces nouveaux défis, la programmation réactive, fondée sur les principes du Reactive Manifesto, propose un paradigme plus adapté pour concevoir et développer des applications Java hautement réactives, capables de s'adapter aux fluctuations de charge et de garantir une faible latence. -Pour explorer la programmation réactive, il est utile de comprendre les systèmes non réactifs traditionnels et leurs inconvénients, -en particulier en ce qui concerne l'utilisation des ressources et la gestion des événements. +Pour explorer la programmation réactive, il est essentiel de bien comprendre le fonctionnement des systèmes traditionnels non réactifs et leurs + limites. Cela inclut une clarification des termes synchrone et asynchrone ainsi que bloquant et non bloquant. -Les systèmes non réactifs, aussi appelés systèmes synchrones ou bloquants, sont les approches traditionnelles utilisées dans la -programmation. Voici quelques caractéristiques clés{nbsp}: +Voici une clarification : +* Synchrone : Les opérations se déroulent séquentiellement, une tâche ne commence que lorsque la précédente est terminée. Le contrôle revient à l'appelant uniquement après la fin de l'exécution de l'opération. +* Asynchrone : Les opérations peuvent être déclenchées sans attendre leur achèvement. Le contrôle revient immédiatement à l'appelant, et les résultats sont généralement traités via des rappels (callbacks), des promesses ou des mécanismes similaires. +* Bloquant : Une opération est dite bloquante si elle empêche l'appelant de continuer tant qu'elle n'est pas terminée (exemple classique : lecture d'un fichier ou attente d'une requête réseau). +* Non bloquant : Une opération est non bloquante si l'appelant peut continuer à exécuter d'autres tâches en attendant que l'opération se termine (souvent en vérifiant l'état de l'opération ou via des mécanismes d'interruption). -* Traitement séquentiel : une tâche doit généralement attendre la fin de l'exécution de la tâche précédente avant de commencer, +Les notions synchrone/bloquant et asynchrone/non bloquant ne sont pas synonymes. -* Blocage des ressources : les systèmes non réactifs bloquent souvent des ressources (comme des threads ou des connexions réseau) en attendant des résultats, +Une opération synchrone peut être bloquante ou non bloquante. +Une opération asynchrone peut être bloquante ou non bloquante. -* Gestion des événements complexes : la gestion des événements dans les systèmes non réactifs peut devenir complexe et difficile à maintenir, surtout lorsque le nombre d'événements augmente +Les systèmes non réactifs, aussi appelés systèmes synchrones ou bloquants, sont les approches traditionnelles utilisées dans la +programmation. Voici quelques caractéristiques clés{nbsp}: -* Latence élevée : en raison de la nature bloquante de ces systèmes, ils peuvent entraîner une latence élevée, surtout dans les applications où la rapidité de réponse est cruciale +* Utilisation inefficace des ressources: chaque thread ou processus peut attendre, bloqué sur des opérations I/O (entrées/sorties), réduisant ainsi l'efficacité du traitement parallèle. +* Difficultés de scalabilité: ajouter plus de threads pour gérer un plus grand nombre de requêtes augmente la consommation de mémoire et entraîne des coûts de commutation de contexte. +* Latence accrue: les opérations bloquantes imposent une attente, ce qui augmente les temps de réponse pour les utilisateurs ou les systèmes. +* Complexité dans la gestion de la concurrence: les développeurs doivent souvent gérer manuellement les verrous, les mutex ou d'autres mécanismes pour coordonner l'accès concurrent aux ressources +* Faible adaptabilité aux environnements modernes: les systèmes modernes, comme les microservices ou les applications cloud, nécessitent une gestion flexible des interactions réseau et des appels API. Les modèles non réactifs sont moins adaptés à ces environnements. -* Scalabilité limitée : comme chaque requête ou tâche peut nécessiter son propre thread ou processus, l'augmentation du nombre de requêtes peut rapidement saturer les ressources du système Pour surmonter ces limitations, les systèmes réactifs offrent une alternative en se concentrant sur l'asynchronisme, non-bloquant, et l'efficacité dans l'utilisation des ressources. Ils permettent de créer des applications qui sont plus réactives, plus résilientes, et plus scalables, en répondant efficacement aux événements et en @@ -39,7 +47,7 @@ des ressources. Ils permettent de créer des applications qui sont plus réactiv == Les principes de la programmation réactive -Les principes de la programmation réactive sont encapsulés dans le "Manifeste Réactif", qui énonce quatre caractéristiques clés{nbsp}: +Les principes de la programmation réactive sont décrites dans le "Manifeste Réactif", qui énonce quatre caractéristiques clés{nbsp}: * Responsive (Réactif) : les systèmes réactifs répondent rapidement aux utilisateurs pour garantir une expérience fluide et interactive. @@ -49,7 +57,9 @@ Les principes de la programmation réactive sont encapsulés dans le "Manifeste * Message-Driven (Basé sur les Messages) : les systèmes réactifs communiquent par la transmission de messages asynchrones, facilitant la connexion et le découplage des composants. -== Les bibliotheques de la programmation réactive sont basés sur deux modèles{nbsp}: +== Les bibliotheques de la programmation réactive + +Les bibliotheques de la programmation réactive sont basés sur deux modèles qui ont été portées dans le JDK 9 avec l'API Flow * ReactiveX : ReactiveX a été conçu pour fournir une API unifiée pour le traitement de collections asynchrones, en s'inspirant des méthodes des collections synchrones (comme map, filter, reduce). Il est souvent utilisé pour gérer des événements utilisateur, des requêtes @@ -61,7 +71,7 @@ réseau, et d'autres opérations asynchrones dans des applications interactives. Dans cet article, on va s'intéresser à Reactor qui est une implémentation de Reactive streams. -Les objectifs principaux de Reactive Streams sont {nbsp}: +Les objectifs principaux de Reactive Streams sont{nbsp}: * Asynchronisme : gérer les flux de données de manière non bloquante et asynchrone. @@ -81,10 +91,10 @@ Les principales interfaces de Reactive Streams sont{nbsp}: == Le Project Reactor : -Reactor est une bibliothèque réactive pour Java développée par Pivotal (maintenant VMware) et intégrée dans l'écosystème Spring. Elle fournit une implémentation de Reactive Streams et permet de +Reactor est une bibliothèque réactive pour Java développée par Pivotal (maintenant Broadcom) et intégrée dans l'écosystème Spring. Elle fournit une implémentation de Reactive Streams et permet de construire des applications non bloquantes, asynchrones, et scalables. Reactor est au cœur de Spring WebFlux, le module réactif Web de Spring Framework. -Les principales abstractions fournies par Reactor sont {nbsp}: +Les principales abstractions fournies par Reactor sont{nbsp}: * 'Mono' : représente un flux réactif qui produit au maximum une seule valeur. @@ -102,11 +112,11 @@ En pratique un 'Flux' peut être sérialisé sous plusieur formes{nbsp}: == Spring Web Flux avec Reactor -Spring Web Flux fait partie de projet Spring 5 : c'est un module Spring basé sur une API HTTP exposée à la source sur reactive Streams dans lequel +Spring Web Flux fait partie de projet Spring 5 : c'est un module Spring basé sur une API HTTP exposée à la source sur Reactive Streams dans lequel on continue à utiliser les mêmes annotations pour les contrôleurs Spring MVC (`@Controller`, `@RequestMapping`, etc). Cependant au lieu d'utiliser des types de retour `List`, `T` ou `void`, on utilise `Flux` ou `Mono`. -=== Les composants de Spring WebFlux {nbsp}: +=== Les composants de Spring WebFlux * Les contrôleurs réactifs : comme dans Spring MVC, mais avec des types réactifs `Mono` et `Flux`. @@ -120,23 +130,23 @@ des types de retour `List`, `T` ou `void`, on utilise `Flux` ou `Mono`. * Performance : adapté pour les applications nécessitant une faible latence et une haute performance. -* Flexibilité : peut être utilisé pour des microservices, des applications Web, ou même des applications fonctionnant avec d'autres paradigmes réactifs comme RxJava. +* Flexibilité : peut être utilisé pour des microservices, des applications Web, ou même des applications fonctionnant avec d'autres implémentations réactifs comme RxJava. -==== Les inconvénients : +==== Les inconvénients Bien que la programmation réactive soit un outil puissant pour de nombreuses applications modernes, elle présente également des inconvénients. -* Débogage et test complexes : Les applications réactives introduisent des comportements asynchrones difficiles à tracer, rendant le débogage et la compréhension des erreurs plus compliqués. De même, les tests nécessitent souvent des outils spécialisés pour simuler les flux asynchrones. +* Débogage et test complexes : les applications réactives introduisent des comportements asynchrones difficiles à tracer, rendant le débogage et la compréhension des erreurs plus compliqués. De même, les tests nécessitent souvent des outils spécialisés pour simuler les flux asynchrones. -* Code plus difficile à lire et maintenir : En raison de la composition des flux et des chaînes d'opérateurs, le code réactif peut devenir difficile à comprendre, en particulier pour ceux qui n’ont pas l’habitude de travailler avec ce paradigme. +* Code plus difficile à lire et maintenir : en raison de la composition des flux et des chaînes d'opérateurs, le code réactif peut devenir difficile à comprendre, en particulier pour ceux qui n’ont pas l’habitude de travailler avec ce paradigme. * Coût d'intégration dans les projets existants : Migrer une application traditionnelle vers une approche réactive peut être coûteux et complexe. Il peut être nécessaire de refactoriser une grande partie du code et d’adapter les couches d’infrastructure. -* Pas toujours adapté : Toutes les applications n'ont pas besoin des avantages de la programmation réactive, comme la haute disponibilité ou l'évolutivité massive. Pour des applications simples ou à faible trafic, l'approche réactive peut introduire une complexité inutile. +* Pas toujours adapté : toutes les applications n'ont pas besoin des avantages de la programmation réactive, comme la haute disponibilité ou l'évolutivité massive. Pour des applications simples ou à faible trafic, l'approche réactive peut introduire une complexité inutile. == La configuration d'un projet Spring WebFlux -=== La configuration Maven : +=== La configuration Maven Pour configurer un projet Maven avec Spring WebFlux et Reactor, il faut ajouter les dépendances appropriées dans le fichier pom.xml : [source,plain] @@ -153,54 +163,55 @@ Pour configurer un projet Maven avec Spring WebFlux et Reactor, il faut ajouter ---- -=== La création d'un contrôleur réactif : +=== La création d'un contrôleur réactif Nous allons utiliser un contrôleur contient deux méthodes : -*La première méthode : retourne un Mono créé à partir d'une valeur unique fournie en paramètre. +* La première méthode : retourne un 'Mono' créé à partir d'une valeur unique fournie en paramètre. -*La deuxième méthode fournit un flux (Flux) représentant une séquence d'entiers allant de 1 à 10, avec un délai de 100 millisecondes entre chaque élément émis. +* La deuxième méthode fournit un flux (`Flux`) représentant une séquence d'entiers allant de 1 à 10, avec un délai de 100 millisecondes entre chaque élément émis. Si un client appelle l'API /numbers, il recevra chaque nombre (de 1 à 10) avec un intervalle de 100 millisecondes entre eux. [source,java] ---- -@RestController - public class ReactiveController { + @RestController + public class ReactiveController { @GetMapping("/hello") - public Mono sayHello() { - return Mono.just("Hello, WebFlux!"); + public Mono sayHello() { + return Mono.just("Hello, WebFlux!"); } @GetMapping("/numbers") - public Flux getNumbers() { - return Flux.range(1, 10).delayElements(Duration.ofMillis(100)); - } -} + public Flux getNumbers() { + return Flux.range(1, 10).delayElements(Duration.ofMillis(100)); + } + } ---- -=== Un exemple d'utilisation de WebClient : +=== Un exemple d'utilisation de WebClient -WebClient C'est une classe fournie par Spring WebFlux pour effectuer des appels HTTP non bloquants (client HTTP réactif). +'WebClient' est une classe fournie par Spring WebFlux pour effectuer des appels HTTP non bloquants (client HTTP réactif). -Nous allons initialiser un WebClient par la methode create("http://example.com") pointant vers l'URL de base http://example.com +Nous allons initialiser un `WebClient` en invoquant la méthode `create("http://example.com")` en lui passant en paramètre l'URL de base `http://example.com`. -La méthode get() initie une requête HTTP de type GET, tandis que uri("/api/data") spécifie le chemin relatif de l'API -cible (ajouté à l'URL de base du WebClient). La méthode retrieve() exécute la requête et prépare la réponse pour être traitée. -Enfin, bodyToMono(String.class) extrait le corps de la réponse HTTP et le convertit en un objet réactif de type Mono, +La méthode `get()` initie une requête HTTP de type `GET` et la méthode `uri("/api/data")` spécifie le chemin relatif de l'API. +cible (ajouté à l'URL de base du `WebClient`). La méthode `retrieve()` exécute la requête et récupère la réponse pour être traitée. +Enfin, `bodyToMono(String.class)` extrait le corps de la réponse HTTP et le convertit en un objet de type Mono, permettant de manipuler la réponse asynchrone dans un pipeline réactif. Si la requête réussit, le contenu de la réponse sera -disponible sous forme de chaîne dans le Mono. +disponible sous forme de chaîne dans le `Mono`. [source,java] ---- -public class WebClientExample { - private final WebClient webClient =WebClient.create("http://example.com"); - public Mono fetchData() { - return webClient.get().uri("/api/data") .retrieve() - .bodyToMono(String.class); - } - } +public class WebClientExample { + private final WebClient webClient = WebClient.create("http://example.com"); + + public Mono fetchData() { + return webClient.get().uri("/api/data").retrieve() + .bodyToMono(String.class); + } +} ---- === La gestion du backpressure @@ -210,23 +221,26 @@ Avec Reactor, vous pouvez contrôler le backpressure via des opérateurs comme ` Exemple d'utilisation de `limitRate` pour réguler la consommation des données : -La methode limitRate(5) applique un mécanisme de contrôle du flux (backpressure) pour limiter la consommation à un maximum de 5 éléments à la fois. Enfin, -un abonné est attaché au flux avec subscribe(), qui imprime chaque élément reçu via un callback, permettant de traiter les données au fur et à mesure de leur +La methode `limitRate(5)` applique un mécanisme de contrôle du flux (backpressure) pour limiter la consommation à un maximum de 5 éléments à la fois. Enfin, +un abonné est attaché au flux avec `subscribe()`, qui affiche chaque élément reçu via un callback, permettant de traiter les données au fur et à mesure de leur arrivée. Ce code est adapté au traitement de grandes quantités de données de manière asynchrone et contrôlée. [source,java] ---- -Flux flux = WebClient.create("http://example.com") - .get() - .uri("/api/large-stream") - .retrieve() .bodyToFlux(Integer.class) - .limitRate(5); - flux.subscribe(data -> { System.out.println("Received: " + data);}); - + Flux flux = WebClient.create("http://example.com") + .get() + .uri("/api/large-stream") + .retrieve() + .bodyToFlux(Integer.class) + .limitRate(5); + flux.subscribe(data -> + { + System.out.println("Received: " + data); + }); ---- -= Conclusion +== Conclusion: Spring Reactor propulse le développement d'applications modernes vers de nouveaux sommets en leur conférant réactivité, performance et résilience. En s'alignant sur le Reactive Manifesto, cette technologie ouvre la voie à des systèmes distribués agiles et efficaces. Toutefois, son adoption implique une courbe d'apprentissage From 2728e1ecb678e4a4a77bd68798912f87e63d0e48 Mon Sep 17 00:00:00 2001 From: khairi Date: Thu, 5 Dec 2024 21:55:34 +0100 Subject: [PATCH 23/23] add suggestion --- _posts/2024-11-23-programation-reactive.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_posts/2024-11-23-programation-reactive.adoc b/_posts/2024-11-23-programation-reactive.adoc index 5d901298..883df06c 100644 --- a/_posts/2024-11-23-programation-reactive.adoc +++ b/_posts/2024-11-23-programation-reactive.adoc @@ -140,7 +140,7 @@ Bien que la programmation réactive soit un outil puissant pour de nombreuses ap * Code plus difficile à lire et maintenir : en raison de la composition des flux et des chaînes d'opérateurs, le code réactif peut devenir difficile à comprendre, en particulier pour ceux qui n’ont pas l’habitude de travailler avec ce paradigme. -* Coût d'intégration dans les projets existants : Migrer une application traditionnelle vers une approche réactive peut être coûteux et complexe. Il peut être nécessaire de refactoriser une grande partie du code et d’adapter les couches d’infrastructure. +* Coût d'intégration dans les projets existants : migrer une application traditionnelle vers une approche réactive peut être coûteux et complexe. Il peut être nécessaire de refactoriser une grande partie du code et d’adapter les couches d’infrastructure. * Pas toujours adapté : toutes les applications n'ont pas besoin des avantages de la programmation réactive, comme la haute disponibilité ou l'évolutivité massive. Pour des applications simples ou à faible trafic, l'approche réactive peut introduire une complexité inutile.