Microservices, exemple d’implémentation

Après un premier article décrivant les avantages de l’architecture microservice, il nous semble intéressant d’approfondir encore le sujet en partant d’un besoin business et en y répondant par une implémentation de cette architecture.
Le besoin que nous allions étudier est issu du use-case décrit dans l’article « Architectures de la transformation digitale » et peut-être résumé pour ce qui nous concerne, par les éléments suivants :

  • ClouDigit est leader de la fabrication et distribution en magasin de clou et s’appuie sur une chaine logistique éprouvée et décentralisée ;
  • Cette structure rachète le site clou.net, qui pour sa part, est un acteur incontournable de la commercialisation e-commerce et s’appuie en conséquence sur une plateforme de vente fonctionnelle et une logistique centralisée ;
  • Il est décidé de mutualiser les forces de ces deux structures et ainsi de créer une nouvelle offre commercialisable à partir du site web, en l’occurrence un retrait boutique dans les 2 heures.

Bien entendu, dans le cadre de cette nouvelle offre il ne faut pas décevoir le client final. En conséquence une vérification de la disponibilité des stocks de la/les boutique(s) près de chez lui sera un préalable à la proposition de ce nouveau service.

 

Pourquoi ce sujet ?

Bien entendu, je pourrais vous expliquer qu’en tant qu’auteur de l’article, je fais ce que je veux. Mais je préfère vous expliquer pourquoi une architecture microservice est particulièrement adaptée à ce besoin.

De fait, si on se rappelle le concept des microservices (article « Microservices, le concept. »), et d’après cette définition, un microservice se doit d’être élastique, tolérant, ouvert, minimal et complet auxquels on peut rajouter stable et autonome.

Or, si on détaille notre besoin on constate que :

  • Le besoin est nouveau et n’est couvert par aucune brique du SI existant ;
  • Le périmètre fonctionnel est limité et indépendant des fonctionnalités du site web existant ou des outils de logistique. Il peut donc être décrit comme une fonctionnalité complémentaire et indépendante. Cependant cette fonctionnalité devra pouvoir s’intégrer au site web existant afin que les utilisateurs puissent l’utiliser et devra permettre de faire le lien entre le site e-commerce , sa chaîne logistique centralisée et la chaîne logistique décentralisée de ClouDIgit, permettant ainsi de tirer le meilleur parti des deux. Cette fonctionnalité aura pour objectif de :
    • Connaître les boutiques ;
    • Connaître les stocks de produits des boutiques et leurs mouvements ;
    • Émettre des réservations de stocks ;
    • Transmettre des bons de préparation aux boutiques ;
    • Prévenir un internaute qu’une commande est disponible en boutique ;
    • Avoir connaissance qu’un retrait boutique est effectif ;
    • Mettre à jour les stocks de la boutique.

Ce périmètre restreint et limité peut donc tout à fait être décomposé (ou pris en charge) par un (ou plusieurs) microservice(s).  De plus ils pourront être mis à disposition d’autres applications, afin d’exploiter les données de gestion des stocks et des commandes en boutique de proximité, comme l’application de gestion des approvisionnements …

  • Les concepts et connaissances métiers nécessaires pour répondre à ce besoin ne sont pas dans le scope de l’équipe s’occupant du site web (stock, boutique) et donc certainement, ce n’est pas cette équipe qui s’occupera de cette implémentation ;
  • La criticité de ce module est différente de celle du site web mais surtout ne doit pas impacter/déstabiliser ce dernier en cas d’indisponibilité.

On peut donc remarquer que cette nouvelle fonctionnalité (brique fonctionnelle), doit répondre à des caractéristiques qui correspondent aux problématiques traitées par les architectures microservice.

Besoin business

Les besoins du site web sont :

  • Avoir la liste des agences pouvant effectuer cette opération de retrait boutique (ouverture, localisation et stock suffisant) ;
  • Pouvoir choisir une boutique de retrait ;
  • Afficher les coordonnées de l’agence choisie (checkout et email de confirmation de commande) ;
  • Etre assuré que le stock est réservé, jusqu’à la fin de la transaction (expérience utilisateur).

Les besoins de la boutique sont :

  • Etre informé qu’une commande doit être préparée ;
  • Ne pas tomber en rupture de stock et pouvoir préparer la commande ;
  • Pouvoir indiquer qu’une commande a été préparée et que l’internaute peut passer retirer sa commande ;
  • Indiquer que la commande a été retirée par l’internaute (maj des stocks).

 

Organisation microservice

De fait, l’analyse des besoins et des fonctionnalités de ces derniers montrent qu’ils peuvent être décomposés en trois fonctions indépendantes … ça sera les 3 microservices :

  • Les boutiques ;
  • Les stocks ;
  • Les demandes de retrait boutique.

Ce sont les trois microservices que nous allons donc implémenter dans notre architecture et détailler ci-dessous.
Ces trois microservices communiqueront par l’intermédiaire de deux mécanismes : API REST (synchrone) et bus de messages (asynchrone).

Pour mémoire et pour rappel, les API REST sont le moyen d’exposer les fonctionnalités rendues par les microservices à des clients extérieurs (ici le site web, demain une application mobile ou un autre client ayant besoin de ces services), mais servent très peu à communiquer entre eux, puisqu’un microservice est autonome (d’un point de vue données et fonctionnalités).

Par contre si deux microservices doivent échanger de l’information, la bonne pratique veut qu’ils communiquent par un bus de message. Le cas d’une communication entre deux microservices par message est lorsqu’un microservice doit signaler qu’il a fini son traitement et que le résultat doit être traité par un autre microservice.

Le seul cas où deux microservices communiquent par API REST est lorsqu’un microservice doit appeler un microservice d’un tiers (ex : mon microservice a besoin de récupérer des données météo qui sont fournies par un organisme externe ou dans notre cas appeler les services de géolocalisation du fournisseur de gestion des tournées de livraison).

Ainsi, concernant la communication asynchrone utilisée par les microservices, nous allons baser notre implémentation sur un bus applicatif et en l’occurrence par l’abonnement à certains événements.

Nous distinguerons deux types d’événements :

  • Des événements d’action dont le but est de lancer des actions.

Exemples :

    • Maj des stocks ;
    • Demande de retrait boutique.
  • Des événements de synchronisation qui sont issus soit des microservices, soit de l’environnement extérieur et qui vont permettre de synchroniser les bases internes.

Exemples :

    • Modification de stock physique ;
    • Modification d’information sur une agence.

Bien entendu, plusieurs microservices peuvent s’abonner au même événement (mais pas dans notre exemple).

 

Le microservice « demande retrait boutique » (DRB)

 

Ce microservice ne contiendra qu’une table, elle est cependant vitale à toute cette implémentation.
Cette table contiendra les informations suivantes :

  • Identifiant unique de réservation ;
  • Identifiant du panier (clef unique du site web) ;
  • Identifiant boutique ;
  • Identifiant produit ;
  • Quantité de la commande ;
  • Date et heure de la réservation (si on veut gérer en automatique, l’abandon de panier et donc l’annulation automatique de réservation au bout d’un certain temps – non abordé ici) ;
  • Statut de cette demande (potentielle / annulée / confirmée / retrait prêt / retirée) ;
  • Numéro de commande web (à partir du statut confirmée) ;
  • Information sur l’internaute (à partir du statut confirmée).

L’identifiant unique de réservation est l’information que devra transmettre le site web lors de la validation finale de la commande (après le paiement) .

Le microservice exposera via son API REST les services permettant aux clients de :

  • Lister les boutiques disponibles pour un retrait ;
  • Faire une réservation de stock ;
  • Interroger une réservation ;
  • Lister les commandes en attente de préparation et/ou à retirer ;
  • Changer le statut d’une commande.

    Il permettra également aux autres microservices : 

    • D’être informé du changement de statut d’une commande.

 

 

Le microservice  « boutique »

 

C’est un microservice dont la structure BDD contiendra :

  • L’adresse de la boutique ;
  • Les horaires d’ouverture des boutiques.

Le microservice exposera via son API REST les services permettant aux clients :

    • D’obtenir la liste des boutiques ouvertes près d’une localisation ;
    • D’obtenir des informations sur une boutique.
  • Par abonnement :
    • De synchroniser l’ERP avec la base d’agence utilisée par le microservice ;
    • D’être informé qu’une nouvelle commande de « retrait boutique », doit être traitée par une agence.

 

 

 

 

Le microservice  « stock »

C’est un microservice dont la structure BDD contiendra  :

  • Un code produit et un libellé ;
  • Une structure détaillant :
    • Code produit ;
    • Identifiant agence ;
    • Quantité en stock ;
    • Quantité réservée.

Le microservice exposera via son API REST les services permettant aux clients :

  • D’obtenir le libellé d’un produit ;
  • D’obtenir une quantité de stock disponible dans une boutique.
  • Par abonnement :
    • Synchroniser l’ERP avec la base produit utilisée par le microservice ;
    • Synchroniser le stock du produit avec les autres composantes du SI ;
    • Faire une réservation de stock ;
    • Mettre à jour un stock.

 

 

 

Ainsi comme on le voit sur nos 3 microservices,  deux sont très simples (boutique et stock) et demanderont très peu d’évolution à moyen terme.
Le microservice « demande retrait boutique », lui est un peu plus complexe, mais finalement si vous regardez bien, pas tant que ça (Il y a beaucoup de schémas).
Donc en résumé, et pour l’instant, nous avons une architecture simple, qui répond aux besoins et qui va s’intégrer facilement.

Intégration des microservices

Sur le site web

Choix d’une boutique :

Le besoin du microservice est de connaître un identifiant unique de panier, connaître la localisation de l’internaute, le produit et la quantité commandée avant de pouvoir potentiellement proposer une liste de boutiques possibles pour le retrait boutique.

L’affichage de cette liste sera effectué indirectement , par réception de l’API d’un flux de données qui sera intégré et affiché après retraitement et validation par le client.
La présentation et l’action de choisir la boutique est à la discrétion de l’équipe web, mais devra de toute manière lors du choix appeler le microservice et l’API « Faire une réservation de stock ».

Le microservice aura également besoin de communiquer et stocker l’identification de réservation et l’identification de la boutique sur la commande. Pour ce faire, il faudra ouvrir une API se basant sur l’identifiant panier.

 

Affichage/utilisation des informations d’une boutique :

Appel du microservice « Interroger une réservation ».

Validation de la commande :

A l’enregistrement de la commande, génération d’un message « Changement-statut-commande » pour confirmer la commande.
Le microservice aura également besoin de lire des informations sur la commande (No de commande, information sur le client). Demande donc d’une API de lecture implémentée sur le site web.

Dans l’extranet « boutique »

 

Commande prête ou retirée par le client

Comme pour le site web cette liste sera affichée indirectement, par réception de l’API d’un flux de données et intégration et l’affichage de ces données après retraitement.
La présentation et l’action de choisir la boutique sont à la discrétion de l’équipe intranet, mais devront de toute manière lors du choix appeler le microservice et l’API « Changement-statut-commande »

 

Conclusion

 

En conclusion le workflow complet de cette implémentation, peut donc résumé par le schéma suivant :

Comme on peut le voir, cette architecture est simple et son intégration au sein d’outils tiers aisée. Elle permet de gérer la scalabilité et la flexibilité de ces services métiers indépendamment du reste du système. Mais, un autre avantage est que cette architecture, et l’implémentation de ces microservices, permet à toutes les applications du système d’information d’utiliser ces informations et ces fonctionnalités en appelant les interfaces fournies. L’application utilisant les fonctionnalités n’a alors pas à s’occuper de la logique métier propre à ces fonctions.

 

La difficulté est déportée alors du côté de l’implémentation du microservice sans impact sur le front
De la même manière, en cas de défaillance des microservices, que se passe-t-il sur le front-office ? Rien.
Certes on ne propose pas de retrait boutique mais on continue à vendre, le dysfonctionnement du microservice est limité à son domaine et n’impacte pas ; ne doit pas impacter l’application où il est inclus.
Cependant, si cette approche limite les dysfonctionnements, elle a également un effet négatif.
C’est pour cela qu’il est primordial dans le cadre d’implémentation de cette architecture de mettre en place des outils de monitoring pointus et détaillés permettant de :

  • Remonter les anomalies des microservices,  et donc d’identifier les dysfonctionnements ;
  • Surveiller leurs capacités (temps de réponses, trafic entrant) et en conséquence agir sur le dimensionnement de l’architecture.

Comme je l’espère, l’implémentation des microservices est maintenant démystifiée et passée du stade « oui je connais » à « oui en effet je comprends ».

 

Microservices, concept

 

Pour mémoire lors d’un précédent article, nous avons présenté le cas d’une fusion de deux entreprises ClouDigit et Clou.net. Voici le lien pour ce Use Case : Article Précédent.

Dans le cadre de cette fusion, un des enjeux à court terme, est d’utiliser le site web de Clou.net afin de proposer une nouvelle fonctionnalité, qui permettra de tirer parti de la force du réseau des 200 magasins et de la chaîne logistique de ClouDigit : une fonction de retrait en boutique dans les 2 heures, si les stocks de la boutique la plus proche le permettent.
Ce service est inexistant dans le site Web de Clou.net, également utilisé par ClouDigit, qui quant à elle fournira le service physique/opérationnel de livraison en deux heures.
Dans ce contexte un pattern d’architecture (modèle d’architecture) permet de répondre à cet enjeu : les architectures orientées « microservices ».

Microservices : concept

L’objectif de cet article est de faire une présentation simple et compréhensible du pattern d’architecture « microservices » : ses origines, les concepts et les enjeux/problématiques couverts.

Un second article « Microservices : exemple d’implémentation », détaillera quant à lui un exemple de mise en place technique des microservices sur la base du besoin issu de notre Use Case, en l’occurrence le « retrait-boutique ».

Origine

Pour mieux comprendre les microservices, il faut en connaître ses origines.
Ce terme proviendrait d’un échange entre plusieurs architectes logiciel venant de différents horizons qui, après un échange de plusieurs jours, en sont arrivés à la conclusion suivante :

<< Les systèmes d’informations sont trop grands/gros/imbriqués et donc difficilement maintenables >>. Force est de constater qu’ils sont également difficilement adaptables et évolutifs.
Ce constat s’est transformé et est devenu « Comment construire un système d’information évolutif et maintenable ? » et ils ont nommé cette architecture idyllique les micro apps.

Bien sûr, depuis ce brainstorming au début des années 2010, ce modèle d’architecture applicative s’est transformé et affiné. Il est, depuis 2014, parfaitement opérationnel, c’est le modèle d’architecture « microservices ».
Le modèle d’architecture « microservice » est souvent opposé au modèle d’architecture monolithique.

Concept

Si l’on se base sur la définition de TOGAF®, fournie par l’Open Group, le modèle d’architecture microservices, repose sur la définition et la création de systèmes/composants indépendants, auto-porteurs et alignés avec des activités métier. Un microservice est un service qui implémente une fonction métier unique, indépendante des autres instances et des autres services.
Les caractéristiques principales d’un microservice sont d’être :

  • Minimal
  • Complet
  • Ouvert
  • Élastique
  • Tolérant
  • Déployable unitairement et avoir un cycle de construction et de déploiement automatisé (DevOps).

Détaillons un peu, les caractéristiques principales des microservices.

Minimal

Un microservice est avant tout un service qui ne s’occupe que d’une entité fonctionnelle et une seule, de bout en bout, afin de rester simple et d’être indépendant des autres.
Quand le service a besoin de faire une interaction en dehors de son domaine, il se lie par API REST ou message.

Cette approche a comme conséquence indirecte de réduire :

  • La taille d’équipe intervenant sur l’implémentation (2 pizza team) ;
  • Le temps de formation de nouveaux intervenants dans l’équipe ;
  • Le temps des tests automatiques post-livraison.

Et donc, de manière générale, il augmente la qualité du livrable.

Complet

Un microservice se doit de limiter son interaction avec le reste du SI.
Dans l’idéal, il doit héberger la totalité des informations/données utilisées lors de son exécution en interne.

Cette isolation des données a certaines incidences, en l’occurrence :

  • Le type de base de données utilisées sera celui le plus adapté au service ;
  • Les données utilisées par le microservice ne seront accessibles de l’extérieur qu’indirectement ;
  • Les phases de synchronisation de données (externe-interne) sont importantes.

Ouvert

Une architecture microservices est avant tout un système de services qui communiquent entre eux.
Il est donc nécessaire pour déclencher, réguler ou inhiber le service d’offrir un interfaçage pertinent.

Deux modes de communication sont couramment employés dans ce style d’architecture.

  • On retrouve, sans surprise, une communication de type REST qui s’appuie généralement sur le protocole HTTP et
  • Une communication de type BUS qui centralise les échanges de messages.

Une autre particularité de l’interfaçage des microservices est sa tolérance.
En effet, il doit :

  • Tolérer des messages même s’ils comportent des données dont il n’a pas besoin ;
  • Pouvoir fonctionner dès lors qu’un message comporte les données suffisantes à son fonctionnement et tolérer l’absence d’informations optionnelles.

L’intérêt de cette tolérance permet de faciliter la migration des autres microservices et/ou le rollback sur les livrables.

Elasticité

Un microservice doit pouvoir s’adapter en termes de capacité, performance et disponibilité indépendamment des autres briques applicatives.
De fait, le besoin de disponibilité, performance et capacité d’un service permettant l’inscription à une newsletter est différent de celui permettant la recherche de produit sur un site e-commerce.

Techniquement, cette scalabilité des microservices est gérée principalement par :

  • Une instanciation multiple des microservices et
  • La mise en place d’un load-balanceur permettant d’adresser les différentes instances suivant le besoin.

Pour cela les microservices pourront s’appuyer sur les technologies de virtualisation (on-premise ou dans le cloud), mais aussi sur les technologies de conteneurisation, ce qui procurera l’avantage supplémentaire d’être indépendant de l’environnement cible de déploiement. Dans ces deux cas la scalabilité sera gérée par l’orchestrateur de virtualisation ou de conteneurisation.
Cependant la scalabilité implique une contrainte d’un point de vue conception du microservice ; ce dernier doit être :

  • Statefull : c’est-à-dire qu’il doit gérer son état et la gestion de cet état lui suffit pour être autonome et indépendant
    OU
  • Stateless : le fonctionnement interne du microservice est totalement indépendant d’un quelconque état, ce qui le rend donc autonome.

Ce point est crucial !

Tolérance

Il est illusoire d’imaginer que les microservices suppriment les dysfonctionnements des applications, cependant ils réduisent leurs impacts.

En effet,

  • Si une instance de microservice « plante », le microservice est toujours fonctionnel ;
  • Si toutes les instances « plantent », seul le service en question est impacté et pas le reste de l’application.

Techniquement, cette tolérance se traduit par :

  • Surveillance nécessaire des instances des microservices ;
  • Isolation des communications inter-service si possible par message (traitement asynchrone).

Déploiement unitaire, continu et automatisé

Ainsi et comme on le voit, un microservice est une entité simple, fonctionnelle et indépendante des autres. Les caractéristiques d’un microservice permettent d’avoir un cycle entre le build et la mise en production plus rapide, incluant le développement, et les tests. En plus de permettre la mise à disposition rapide du microservice en toute maîtrise, ces caractéristiques permettent également une automatisation plus simple des opérations de gestion du cycle de vie du microservice – build, tests et déploiement.
En effet, en augmentant la qualité du livrable, en automatisant les tests et en réduisant l’impact des dysfonctionnements, on se retrouve avec une évolution qui peut être livrée en production en toute sérénité.

Le modèle d’architecture microservice est donc particulièrement adapté à la mise en place et l’adoption d’une approche DevOps.

Conclusion

Si on enlève encore le risque d’erreur humaine lié à un process de déploiement manuel, on obtient enfin ce qui fait que cette architecture est adoptée par les plus grandes structures :

  • La réactivité et l’évolutivité en toute sécurité aux demandes de changement des clients ou d’un marché ;
  • La baisse de complexité du développement, des opérations et de la gestion des micrsoervices ;
  • La réduction de la complexité fonctionnelle des composants applicatifs.

Par contre le modèle d’architecture microservice apporte également son lot de contraintes :

  • Une complexité de gestion plus importante de l’ensemble des microservices liée à l’aspect distribué des différentes fonctions métier dans les différents services :
    • Des tests d’intégration plus conséquents et complexes ;
    • La gestion de la communication inter-services plus complexe.
  • Une gestion des déploiements plus complexe ;
  • Une supervision plus complexe.

Après toute cette théorie, je vous propose de passer à la pratique dans notre prochain article.

Pourquoi et comment intégration et anticipation apportent-elles un meilleur ROI ?

La réalisation de projets n’est pas un long fleuve tranquille.

Au fur et à mesure que le projet avance, des événements non prévus se produisent.

Les risques se matérialisent.
Les tâches prennent du retard.
Les ressources tombent malades.
Le projet change d’objectif.
Face à ces aléas, deux comportements distincts sont possibles :

La gestion de l’événement

Ce comportement défensif tente de gérer les influences extérieures afin que le projet ne soit pas touché.
En l’occurrence, on va essayer d’éviter le risque, prendre de nouvelles ressources ou replanifier en espérant tenir le planning annoncé.

L’intégration de l’événement dans le projet

Il s’agit dans ce cas d’intégrer le changement au sein du projet et alors modifier ce dernier pour s’assurer qu’il est toujours structurellement sain et réalisable.
On va examiner au niveau planning l’impact de l’événement, attribuer des ressources « au cas où », envisager une autre façon d’effectuer l’action tout en gérant les risques et en communiquant.
Cette remise à plat du projet est la seule permettant d’assurer et de garantir la finalité et le ROI du projet, car l’aléa a été maîtrisé,intégré et les plannings seront tenus.

Bien entendu, l’intégration est sans aucun toute la meilleure approche pour gérer les écueils lors de la vie d’un projet, mais il est également intéressant de parler d’une troisième méthode qui est supérieure aux deux autres, l’anticipation.

« Prévoir, c’est déjà agir », dit un adage populaire et en effet on peut remarquer que cela s’applique également dans la gestion de projet.

Si les événements extérieurs sont parfois imprévisibles (dépôt de bilan d’un fournisseur), dans la plupart des cas le chef de projet peut, par anticipation les limiter, voire les supprimer.
Anticiper, c’est lister tous les éléments pouvant déstabiliser un projet et s’assurer que ces événements perturbateurs n’arriveront pas.

Cela peut être par exemple :

  • S’assurer auprès d’un fournisseur que le livrable prévu dans 15 jours est dans les clous ;
  • Que les machines prévues pour installer le livrable sont prêtes et accessibles ;
  • Que la salle prévue pour accueillir l’équipe qui doit tester le livrable est disponible et ouverte.

Cette approche systématique et permanente de problème inexistant (qui n’existe pas/qui n’existe pas encore), ces informations et communications incessantes entre le chef de projet et les intervenants internes et externes, sont des composantes clefs de la réussite des projets et la garantie du respect délai/planning, car elles évitent de fait le passage par la case « problème à régler ».

Bien entendu, l’anticipation n’est pas seulement technique mais également organisationnelle comme on le voit dans cet exemple. On peut aussi étendre cette notion d’anticipation pour parler plus généralement de pilotage de projet par les risques.
Nous traiterons dans un prochain article le passage du pilotage de l’anticipation au pilotage par les risques.