Cet article est la seconde partie du premier sur le thème d'architecture micro-services (AMS ou MSA). Dans cette partie, comme promis, nous passons à la pratique.
Rappelons à nouveau les inconvénients d'une application monolithique traditionnelle (tous les services dans une seule archive, .war par exemple):
- L'application monolithique est tellement grosse que la correction d'un simple bug devient consommatrice de temps,
- Impossible pour un développeur de comprendre cette application réalisée durant plusieurs années,
- La difficulté de changer quoique ce soit dans une application monolithique. Ajouter une nouvelle fonctionnalité devient risqué !
- Certaines applications monolithiques nécessitent plusieurs minutes pour être lancées, ainsi beaucoup de temps sert à relancer afin de les déboguer,
- La fiabilité de l'application monolithique est faible car si un des services est down c'est toute l'application qui est down puisque tous les services sont exécutés dans le même processus. On peut illustrer ce point avec ce scénario : imaginez un site e-commerce devant afficher les produits et les recommandations associées. Un développeur lambda réalise une méthode du service qui va chercher la liste des produits et la liste des recommandations de chaque produit. Mais s'il n'arrive pas à récupérer, pour un produit quelconque, sa liste de recommandations, il décide (forcé?) d'afficher une page d'erreur ! Alors qu'il était possible et raisonnable de juste afficher la liste des produits même sans les recommandations.
- Dans une application monolithique difficile de définir l'axe à retenir pour rendre l'application "scalable" : C'est à dire, imaginons qu'un des services a besoin d'augmenter le CPU pour effectuer des calculs or le service voisin n'a pas du tout ce besoin mais comme il partage la même configuration machine, difficile de trouver un compromis. Alors la puissance CPU pour toute l'application et c'est parti.
Rappelons aussi que l'objectif principal de l'AMS est de rendre agile le développement et le déploiement.
Mais cette architecture vient avec son lot d'inconvénients :
- L'inconvénient majeur de micro-services est de croire que, de part son nom, le découpage en micro services est en soit l'objectif final.
- L'autre inconvénient majeur est de maîtriser la complexité liée à la communication, dans un système distribué, entre ces services.
- Un autre inconvénient ou défi à relever est de revoir l’architecture de la partie base de données (back BDD).
Jusqu'ici la solution de gérer les transactions métier de plusieurs entités est presque devenue archiconnue lorsqu'une seule base est définie. Mais avec l'architecture micro-services, il faudrait gérer plusieurs bases de données car chaque service peut avoir besoin de sa propre base de données.
Penser aux transactions distribuées pour gérer la multiplicité des bases ne peut pas être l'option la plus facile à retenir.
Nous insistons un peu : dans une architecture AMS, le focus doit être fait non seulement sur le découpage des services mais aussi et surtout sur les interactions entre ces services.
Aussi, nous devons éviter d'appeler un service directement via sa location (même si elle est configurée selon la plateforme cible de déploiement).
Par exemple, évitez d'utiliser l'url: http[s]://[host]:[port]/[nameservice] afin ne pas créer un couplage fort entre les services.
Lorsque les services sont déployés et exécutés dans un système distribué (chaque instance est souvent une VM (cloud) ou encore un container Docker). Par conséquent, nous ne savons rien sur les ip ou les dns des machines qui hébergent ces services. D'où l'intérêt du "Service Discovery".
Pour bien démarrer la partie pratique et afin de faciliter la prise en main, j'ai décidé d'isoler les difficultés et de simplifier les notions abordées en procédant par étape.
Nous commençons donc par le thème des interactions entre services ou encore en un mot "Service Discovery". On distinguera le "Server-Side Dsicovery" du "Client-Side Discovery".
Pour en savoir plus sur la notion de "Service Discovery" voir ici.
Comme vous pouvez le constater plus loin, nous avons volontairement choisi l'approche où c'est le client qui s'enregistre dans le "Service Discovery". L'inconvénient de cette approche est de coder cette partie dans chaque service client. Mais avec l'API Spring la tâche est tellement facile.
Il y a certainement d'autres approches possibles exemple un "registrar" qui centralise l'enregistrement des services sans impact sur le code du service client.
Voici le sommaire de ce que nous allons voir, décomposé en deux parties distinctes :
Service Discovery Registry (side server)
- Créer un projet spring-boot afin de centraliser et d'enregistrer les services,
La solution open-source, Eureka, de Netflix et l'API Spring-Cloud rendront cette entreprise facile. - Compléter ou vérifier le pom projet,
- Annoter la classe générée par spring-boot,
- Configurer service Eureka Registry.
Service Discovery Client (client side)
- Créer un second projet spring-boot définissant le micro-service qui sera déployé dans le serveur Eureka.
Tout cela est réalisé de manière automatisée grâce encore à l'API Spring, - Compléter ou vérifier le pom projet,
- Annoter la classe générée par spring-boot,
- Ecrire un RestController pour illustrer les notions de consommation de services via leurs noms enregistrés dans "Eureka Registry".
Les ingrédients de la recette de notre démo sont:
- Entrée: Spring-boot,
- Plat: API Eureka de Netflix & API Spring-cloud,
- Dessert: Rest Spring,
- Java 8 pour ingrédient de base.
Merci de noter que je me suis servi librement du super article de Josh Long sur le thème de micro-services.
PARTIE 1. Service Eureka Discovery / Registry
La réalisation de cette partie peut être décomposée en plusieurs actes:
ACTE 1. Créer le projet spring-boot
Nous partons de la page Spring initilzr pour créer notre projet.
Vous voyez sur la capture ci-dessous que la seule dépendance choisie est "Eureka Discovery". La version 1.3.3 de Spring-Boot a été sélectionnée.
ACTE 2. Vérifier le pom
L'action réalisée à l'étape précédente doit générer ce pom (extrait):
Vous constatez la présence de la seule dépendance intéressante "spring-cloud-starter-eureka-server" déjà évoquée précédemment.
Vous avez aussi certainement noté la présence de la classe java nommée DemoApplication.java (si vous n'avez pas changé le nom de l'artifact dans l'écran initilizr).
ACTE 3. Annoter la classe générée
La classe DemoApplication est générée et annotée avec @SpringBootApplication de Spring-Boot, nous l'annotons encore avec @EnableEurekaServer de spring-cloud (package org.springframework.cloud.netflix.eureka.server.EnableEurekaServer).
Faisant cela, nous avons utilisé la brique de Netflix nommée Eureka qui est un "service discovery ou service registry".
L'annotation @EnableEurekaServer est "side server", fournie par l'api spring-cloud pour faciliter la mise en place de la découverte du service Eureka.
Avec l'acte suivant, nous complétons la configuration du service Eureka via le fichier properties ou yaml.
ACTE 4. Configurer Eureka
Le fichier application.(properties, yml) est généré par spring-boot.
Nous avons retenu le fichier YAML nommé application.yml dont le contenu est comme suit:
ACTE 5. Tester le service Eureka
Il suffit d'exécuter la classe ( clic-droit -> run as -> spring-boot app) puis de saisir dans le browser l'url localhost:8761 pour voir s'afficher la page du service Eureka.
Nous obtenons cette capture:
A ce stade aucune instance de micro-service n'est enregistrée d'où la mention "No instances available".
Je crois que la longueur de cet article m'oblige à remettre le reste à la prochaine partie, dans laquelle, nous enregistrons un premier micro-service client dans le "Service Eureka Discovery". Puis un second service...
Voici un aperçu général des actes que nous aborderons :
PARTIE 2. Service Client Eureka
ACTE 1. Créer le second projet Spring-boot
ACTE 2. Vérifier le pom projet
ACTE 3. Annoter la classe générée
ACTE 4. Configurer Client Eureka
ACTE 5. RestController pour consommer les micro-services
A très vite,
Merci pour l’article !
Nous testons de notre côté Vert.x, ainsi que Dropwizard. As-tu un retour d’expérience à ce sujet ?
Can
Merci pour ce retour, ça fait toujours plaisir 🙂
Désolé je n’ai pas utilisé ni Dropwizard (je préfère spring-rest & spring-boot) ni Vert.x.
Abdou,
Bonjour,
votre article reste inachevé ou vous avez publiez les parties manquantes de « Architecture microservice, spring-boot.. »?. Dans ce cas, je serai ravie de vous lire.
merci pour cet article en attendant la suite…
Bonjour,
Merci pour votre commentaire.
Le troisième volet est en cours de rédaction, il sera publié très prochainement.
c’est pour bientôt l’autre partie?
C’est déjà sorti 🙂 : https://www.sodifrance.fr/blog/architecture-microservice-spring-boot-de-la-theorie-a-la-pratique-part-3/