Be Software Architecture Wise
Be Wise Apps

Read in English · Leer en español · Auf Deutsch lesen

Section 6.3 sur 6.8 · Avancé · 26 min de lecture

Microservices : principes, avantages et coûts

Leçon vidéo

5 min · narré en anglais, avec sous-titres
Écouter seulement (audio)
Lire la transcription

Les microservices font beaucoup parler d’eux, et il est facile de s’y tromper. Vous allez apprendre ce qu’ils sont vraiment, quelle taille doit avoir un service, et ce qu’ils coûtent.

Imaginez une grande aire de restauration plutôt qu’un grand restaurant unique. Chaque stand a sa propre petite équipe, sa propre cuisine et sa propre carte, et peut changer ses recettes sans demander l’avis des autres stands. Les clients commandent à un comptoir d’accueil commun, qui transmet chaque commande au bon stand. L’aire peut s’agrandir en ajoutant des stands, et un incendie dans la cuisine d’un stand ne fait pas fermer les autres. Mais il faut bien que quelqu’un gère le comptoir d’accueil, les livraisons, le nettoyage et les contrôles de sécurité pour tous les stands, et un repas venant de trois stands exige une coordination soigneuse. Les microservices, c’est l’aire de restauration.

Les microservices construisent une application comme un ensemble de petits services. Chacun s’exécute dans son propre processus, est organisé autour d’une capacité métier, peut être déployé seul grâce à un outillage automatisé, et communique avec les autres par des mécanismes légers, comme des API HTTP ou la messagerie. La question la plus difficile est de savoir où tracer les frontières entre les services.

La meilleure réponse est d’aligner chaque service sur un contexte délimité : une partie de l’activité où un modèle et son langage sont cohérents. Une commande désigne un panier dans Commandes, mais une prise en charge et une remise dans Affectation. Un contexte correspond généralement à ce qu’une équipe peut prendre en charge. La propriété qui les définit est la déployabilité indépendante : une équipe peut mettre son service en production sans en mettre aucun autre en production. Cela dépend des contrats, pas des conteneurs : des changements rétrocompatibles et des tests de contrat. Chaque service possède ses données, et aucun autre service ne les lit ni ne les écrit directement. Le prix est élevé. Les jointures deviennent des appels entre services, et une transaction devient une saga qui n’est cohérente qu’à terme. Et la logique métier a sa place dans les services. Le réseau et le courtier de messages ne font que transporter les messages : des extrémités intelligentes et des tuyaux passifs.

Voici la plateforme de livraison de repas en microservices. En haut, trois clients : l’app client, la tablette du restaurant et l’app du livreur. Les requêtes passent par une API gateway, un point d’entrée unique qui gère le chiffrement, l’authentification, les limites de débit et le routage. Gardez-la à l’écart de la logique métier, sinon vous reconstruisez l’ancien bus de services. Vient ensuite un backend for frontend pour chaque type de client : un backend léger, détenu par l’équipe de ce client, qui appelle les services et met en forme les réponses. Puis les services : Commandes, Carte, Tarification, Affectation et Paiements. Chacun possède sa propre base de données, et chacun peut choisir le type de stockage qui lui convient. En bas court un courtier de messages qui transporte des événements comme OrderPlaced. Chaque élément de soutien résout un vrai problème, mais c’est une chose de plus à exploiter.

Alors, quelle taille doit avoir un service ? Il n’existe pas de taille correcte en lignes de code ou en nombre de personnes. Un meilleur outil consiste à peser les forces qui s’exercent sur la granularité des services. Six forces poussent au découpage : le périmètre du service, la fréquence de changement de son code, des besoins de mise à l’échelle très différents, la tolérance aux pannes, la sécurité et l’extensibilité. Quatre poussent à garder les choses ensemble : les transactions qui doivent réussir ou échouer d’un bloc, les flux de travail qui deviendraient de longues chaînes d’appels, le code partagé et les données étroitement liées. La granularité est un équilibre, à trancher au cas par cas.

Voici cet équilibre en pratique. Un service Tarification calcule le total des paniers, y compris les frais de livraison et les promotions. Les promotions changent plusieurs fois par semaine, et chaque mise en production reteste le calcul des frais. Quelqu’un propose un découpage. La volatilité du code plaide fortement en sa faveur. Les promotions changent chaque semaine, les règles de frais chaque trimestre. La tolérance aux pannes plaide modérément en sa faveur. Une règle de promotion erronée a fait planter Tarification deux fois. Avec un service séparé, une défaillance pourrait simplement signifier qu’aucune remise n’est affichée. Le flux de travail plaide modérément contre. Chaque total de panier a besoin des deux, donc un découpage ajoute un saut synchrone et ses modes de défaillance. La décision : extraire Promotions, avec précaution. Tarification l’appelle avec un délai d’expiration de cent cinquante millisecondes et, en cas d’échec, calcule le prix du panier sans remises et le recalcule à l’étape de paiement.

L’échec le plus grave est le monolithe distribué : des services qui partagent une base de données, s’appellent en longues chaînes ou doivent être mis en production ensemble. Tous les coûts de la distribution, et aucune indépendance. Les services d’entités portent des noms communs, comme client ou commande, et ne font guère plus que stocker et récupérer des enregistrements, si bien que chaque processus métier doit en appeler plusieurs. Les services bavards transforment une seule requête utilisateur en dizaines d’appels, si bien que la latence augmente à chaque fonctionnalité. Ce style exige aussi des bases préalables : un provisionnement rapide, la supervision de chaque service et un déploiement automatisé avec un retour arrière facile. Et les équipes doivent exploiter ce qu’elles construisent, en assurant l’astreinte. Les microservices conviennent donc à de nombreuses équipes travaillant sur des domaines bien compris. Ils ne conviennent pas à une petite équipe, ni à un nouveau produit dont le domaine est encore en cours de découverte. C’est un outil qui a un coût, pas une destination.

La section complète présente chaque force de granularité avec un exemple, et la liste complète des anti-patrons. Ensuite, dans la section six point quatre, nous verrons l’architecture pilotée par les événements. À très vite.

Ce qu’il faut savoir

Définition et origine

Les microservices sont un style architectural dans lequel une application est construite comme un ensemble de petits services, chacun s’exécutant dans son propre processus, chacun organisé autour d’une capacité métier, chacun déployable indépendamment grâce à un outillage automatisé, et communiquant par des mécanismes légers tels que des API HTTP ou la messagerie, avec un minimum de gestion centralisée. Ce résumé suit l’article qui a défini le terme pour la majeure partie du secteur : Microservices, de James Lewis et Martin Fowler, publié sur martinfowler.com en mars 2014. L’article indique que le nom a été discuté lors d’un atelier d’architectes logiciels près de Venise en mai 2011, puis adopté par le groupe en mai 2012 ; des entreprises comme Amazon et Netflix travaillaient déjà de cette façon.

Lewis et Fowler n’ont pas donné de définition formelle. Ils ont décrit neuf caractéristiques communes, que les praticiens utilisent encore comme liste de contrôle : la composantisation par les services ; l’organisation autour des capacités métier ; des produits plutôt que des projets ; des extrémités intelligentes et des tuyaux passifs (smart endpoints and dumb pipes) ; une gouvernance décentralisée ; une gestion décentralisée des données ; l’automatisation de l’infrastructure ; la conception pour la défaillance ; et la conception évolutive. Les sections ci-dessous examinent tour à tour les plus significatives d’entre elles sur le plan architectural.

Des services alignés sur les contextes délimités

La question la plus difficile des microservices est de savoir où tracer les frontières. La réponse la plus fiable vient de la conception stratégique pilotée par le domaine (chapitre 5) : un contexte délimité (bounded context) est une partie de l’activité à l’intérieur de laquelle un modèle et son langage sont cohérents. Dans la livraison de repas, « commande » désigne un panier en cours de paiement dans Commandes, un bon à préparer dans le contexte de la cuisine du restaurant, et une prise en charge suivie d’une remise au client dans Affectation. Chaque contexte est un candidat naturel pour un service, ou pour un petit nombre de services détenus par une seule équipe.

Aligner les services sur les contextes délimités leur donne une forte cohésion (ce qui change ensemble vit ensemble) et un faible couplage (les contextes communiquent par quelques contrats explicites, traduits aux frontières). Cela les aligne aussi sur les équipes, car un contexte délimité a généralement la taille de ce qu’une équipe peut comprendre et prendre en charge. Les services découpés selon des couches techniques ou des tables de base de données n’ont aucune de ces deux propriétés, et les anti-patrons présentés plus loin dans cette section en sont pour la plupart la conséquence.

La déployabilité indépendante : la propriété qui les définit

Si une propriété définit les microservices, c’est la déployabilité indépendante : une équipe peut modifier son service et le mettre en production sans modifier, tester ni mettre en production aucun autre service en même temps. Sam Newman, dans Building Microservices (deuxième édition, 2021), la considère comme la propriété à protéger avant toutes les autres, car presque tous les autres avantages en dépendent. Livraison plus rapide, rayon d’impact (blast radius) réduit, mise à l’échelle ciblée et autonomie des équipes disparaissent tous si les mises en production doivent être coordonnées.

La déployabilité indépendante est une propriété des contrats, pas des conteneurs. Deux services déployés séparément mais qui doivent toujours être mis en production ensemble, parce qu’un changement dans l’un casse l’autre, ne sont pas déployables indépendamment. La protéger exige des changements d’interface rétrocompatibles (ajouter des champs, ne jamais en supprimer ni en renommer sans période de dépréciation), des tests de contrat pilotés par le consommateur et des API versionnées, tous traités dans communication et API.

Base de données par service, et extrémités intelligentes avec tuyaux passifs

La gestion décentralisée des données de Lewis et Fowler devient, en pratique, la règle de la base de données par service : chaque service possède ses données, et aucun autre service ne les lit ni ne les écrit directement. Les autres services obtiennent les données par l’API du propriétaire ou par les événements qu’il publie. C’est cette règle qui fait d’un service un quantum distinct : son schéma peut changer, et il peut être mis à l’échelle, sauvegardé et restauré, sans demander l’avis de personne. Chaque service peut aussi choisir le stockage qui lui convient (une base de données relationnelle pour les commandes, un stockage clé-valeur pour les sessions, un moteur de recherche pour les cartes), ce que l’on appelle la persistance polyglotte.

Le prix est élevé et doit être payé en connaissance de cause. Les requêtes qui étaient une jointure SQL entre tables traversent désormais plusieurs services. Les changements qui tenaient en une seule transaction exigent désormais une saga et deviennent cohérents à terme. Le reporting nécessite un pipeline séparé. Le chapitre 7 traite en profondeur de la propriété des données.

L’autre caractéristique aux conséquences architecturales les plus importantes est celle des extrémités intelligentes et tuyaux passifs. La logique métier a sa place dans les services ; le réseau et le courtier de messages (message broker) ne font que transporter les messages. C’est une réaction directe au bus de services d’entreprise de la SOA classique, où les règles de routage, les transformations et les processus s’accumulaient dans un middleware central.

Une topologie microservices pour la livraison de repas

Topologie microservices pour la livraison de repas : trois apps clientes appellent une API gateway, qui route vers un backend for frontend par client ; les BFF appellent des services à grain fin, chacun avec son stockage, qui échangent aussi des événements via un courtier de messagesApp clientTablette restoApp livreurAPI gateway : TLS, authentification, limites de débit, routageBFF clientBFF restaurantBFF livreurchaque service a ses donnéesCommandessa BDCartesa BDTarifssa BDAffect.sa BDPaiementssa BDCourtier de messages : OrderPlaced, PaymentAuthorised, CourierAssigned ...Flèches pleines : appels synchrones. Pointillés : événements publiés et consommés via le courtier.
Les clients accèdent aux services par une passerelle et un backend for frontend chacun ; chaque service possède ses données, et les événements circulent par un courtier.

Patrons de soutien

Un ensemble de patrons de soutien s’est développé autour de ce style. Chacun résout un vrai problème et chacun ajoute un composant à exploiter ; adoptez-les donc quand le problème apparaît plutôt que tous à la fois.

Patrons de soutien courants

PatronProblème résoluCe que c’estPoints de vigilance
API gateway (passerelle d’API)Les clients ne devraient pas connaître les adresses de dizaines de services, ni répéter l’authentification auprès de chacun.Un point d’entrée unique qui termine les connexions TLS, authentifie, limite le débit et route les requêtes vers les services ; il peut combiner plusieurs appels en une seule réponse.Une logique métier qui s’insinue dans la passerelle et recrée un ESB ; un point de défaillance unique qui exige une haute disponibilité.
Backend for frontend (BFF)Une app mobile, une app web et une API partenaire ont besoin de données de formes différentes ; une API générale unique ne sert bien aucune d’entre elles.Un backend distinct et léger pour chaque type de client, détenu par l’équipe de ce client, qui appelle les services et met en forme les réponses. Le nom vient de Phil Calçado, chez SoundCloud ; Sam Newman a popularisé le patron en 2015.Une logique dupliquée entre les BFF ; un BFF qui devient un mini-monolithe.
Découverte de servicesLes instances de service démarrent, s’arrêtent et se déplacent en permanence ; les adresses ne peuvent pas être configurées à la main.Un registre des instances saines du moment, interrogé par les clients ou par un équilibreur de charge. Kubernetes fournit cette fonction au moyen de noms DNS attribués aux Services.Entrées de registre périmées ; clients qui gardent des adresses en cache trop longtemps.
Service mesh (maillage de services)Chaque service a besoin de TLS mutuel, de nouvelles tentatives, de délais d’expiration, de bascule progressive du trafic et de télémétrie ; les implémenter dans chaque langage est du gaspillage.Une couche d’infrastructure faite de proxys (traditionnellement un sidecar à côté de chaque instance de service), pilotée de façon centralisée, comme Istio ou Linkerd.Une complexité opérationnelle considérable ; des nouvelles tentatives configurées à la fois dans le maillage et dans le code multiplient la charge.

Les prérequis de Fowler, et les coûts organisationnels

En août 2014, Martin Fowler a énuméré trois choses qu’une organisation devrait posséder avant même de construire des microservices. Le provisionnement rapide : la capacité de créer un nouveau serveur ou environnement en quelques heures, ce qui suppose de l’automatisation. La supervision (monitoring) de base : des mesures techniques (erreurs, latence, disponibilité) et des mesures métier (commandes par minute) pour chaque service, afin de repérer vite les problèmes. Le déploiement rapide des applications : un pipeline automatisé qui amène vite un service en test et en production, avec un retour arrière facile. Sans cela, de nombreux petits services multiplient le travail manuel. Son idée complémentaire, le surcoût des microservices (microservice premium, 2015), est que ce style comporte un coût fixe en complexité et en productivité qui n’est rentable que pour des systèmes assez complexes pour en avoir besoin.

Les coûts organisationnels sont aussi réels que les coûts techniques. Ce style suppose des équipes durables qui exploitent leurs services en production, selon le principe que le CTO d’Amazon, Werner Vogels, a résumé en 2006 par You build it, you run it (« vous le construisez, vous l’exploitez »). Cela signifie que chaque équipe a besoin de compétences d’exploitation et d’un planning d’astreinte. Il faut une plateforme : pipelines de déploiement, observabilité, gestion des secrets et modèles de services, généralement fournis par une équipe plateforme (chapitre 10). Il faut s’accorder sur des standards transversaux (format de journalisation, identifiants de corrélation, conventions d’API) sans approbation centrale de chaque changement. Et il faut utiliser délibérément la loi de Conway : les frontières des équipes et celles des services doivent correspondre, sinon chaque changement exige la coordination de plusieurs équipes.

Granularité : quelle taille pour un service ?

Il n’existe pas de taille correcte en lignes de code ou en nombre de personnes. Lewis et Fowler ont observé des équipes d’une douzaine de personnes détenant un service et des équipes d’environ six personnes détenant six services, et regrettaient que le mot « micro » attire l’attention sur la taille. Ford, Richards, Sadalage et Dehghani proposent un meilleur outil dans Software Architecture: The Hard Parts (2021) : peser les forces qui poussent à découper un service, qu’ils appellent désintégrateurs de granularité, face à celles qui poussent à le garder entier, les intégrateurs.

Les forces qui s’exercent sur la granularité des services

Six désintégrateurs de granularité poussent à découper un service et quatre intégrateurs poussent à le garder entierGranularitéoù tracer la frontière ?Désintégrateurs : couperIntégrateurs : regrouperPérimètre et fonctionVolatilitéScalabilité et débitTolérance aux pannesSécuritéExtensibilitéTransactions de BDWorkflow et chorégraphieCode partagéLiens entre donnéesForces selon Ford, Richards, Sadalage et Dehghani, Software Architecture: The Hard Parts (2021)
Six désintégrateurs plaident pour des services plus petits ; quatre intégrateurs plaident pour des services plus grands. La granularité est un équilibre, à trancher au cas par cas.

Désintégrateurs et intégrateurs de granularité, avec des exemples tirés de la livraison de repas

ForceSensQuestion à poserExemple
Périmètre et fonctionDécouperLe service fait-il une seule chose cohérente, ou plusieurs choses sans rapport entre elles ?Un service Notifications qui calcule aussi les points de fidélité fait deux métiers.
VolatilitéDécouperUne partie change-t-elle bien plus souvent que le reste ?Les règles de promotion changent chaque semaine ; le reste de Tarification change chaque trimestre.
Scalabilité et débitDécouperLes parties ont-elles besoin de capacités très différentes ?Les mises à jour de position des livreurs arrivent des milliers de fois par seconde ; l’inscription des livreurs, quelques fois par jour.
Tolérance aux pannesDécouperUne défaillance dans une partie en ferait-elle tomber une autre sans nécessité ?Un plantage du générateur de reçus PDF ne devrait pas empêcher la prise de commande.
SécuritéDécouperLes parties ont-elles besoin de contrôles d’accès ou d’audits différents ?Les jetons de cartes bancaires stockés face aux données publiques des cartes de restaurant.
ExtensibilitéDécouperDe nouvelles variantes seront-elles ajoutées souvent ?De nouveaux moyens de paiement tous les quelques mois, chacun déployable séparément.
Transactions de BDGarder ensembleCes changements doivent-ils réussir ou échouer de façon atomique ?Créer une commande et réserver son créneau de livraison.
Workflow et chorégraphieGarder ensembleLe découpage créerait-il de longues chaînes d’appels pour des requêtes ordinaires ?Panier, paiement et statut de commande s’appellent mutuellement à chaque requête.
Code partagéGarder ensembleLes parties partagent-elles une logique métier importante qui change en même temps ?Carte et Tarification partagent des règles complexes d’options de plats.
Liens entre donnéesGarder ensembleLes données sont-elles étroitement liées, avec des jointures et des clés étrangères ?Les commandes et les lignes de commande ; les séparer ne rapporte rien.

Exemple commenté

Exemple commenté : faut-il découper Tarification ?

La plateforme de livraison de repas dispose d’un service Tarification qui calcule le total des paniers : prix des plats, suppléments d’options, frais de livraison (qui dépendent de la distance et de la demande) et promotions (bons de réduction, remises sur la première commande, offres des restaurants). L’équipe promotions livre des changements plusieurs fois par semaine, et chaque mise en production de Tarification exige un passage complet des tests de non-régression du calcul des frais. Quelqu’un propose de découper Tarification en deux services, Frais et Promotions. L’architecte pèse les forces.

Volatilité du code (découper)Forte : les promotions changent chaque semaine, les règles de frais chaque trimestre. Les séparer permettrait de livrer les promotions sans retester les frais.
Scalabilité (découper)Faible : les deux sont appelés une fois par affichage du panier, au même rythme.
Tolérance aux pannes (découper)Modérée : une règle de promotion erronée a fait planter Tarification deux fois. Si Promotions était séparé, une défaillance pourrait se réduire à « aucune remise affichée » tandis que les frais fonctionneraient toujours.
Sécurité (découper)Faible : même sensibilité des données.
Transactions de base de données (garder)Faible : aucune écriture ne doit couvrir les deux ; un bon de réduction est utilisé au moment où la commande est passée, dans Commandes.
Flux de travail (garder)Modérée : chaque total de panier a besoin des deux. Après un découpage, Tarification (ou un BFF) doit appeler Promotions de façon synchrone à chaque affichage du panier, ce qui ajoute un saut réseau et ses modes de défaillance.
Code partagé (garder)Modérée : les deux ont besoin du modèle de panier et des règles d’arrondi monétaire, qui changent rarement.
Relations entre données (garder)Faible : les promotions ne font référence aux restaurants et aux plats que par leur identifiant.
DécisionDécouper, avec précaution : extraire Promotions ; Tarification l’appelle avec un délai d’expiration (timeout) de 150 ms et, en cas d’échec, calcule le prix du panier sans remises et le signale pour un nouveau calcul à l’étape de paiement. Ne partager qu’une petite bibliothèque de modèle de panier, versionnée.

La décision repose sur deux désintégrateurs forts (volatilité et isolation des défaillances) qui l’emportent sur des intégrateurs modérés. Si les promotions avaient dû mettre à jour les mêmes lignes que le calcul des frais dans une seule transaction, la réponse aurait probablement été différente.

Écrire les forces noir sur blanc transforme une affaire de goût en un argument que d’autres peuvent vérifier, et cette trace a sa place dans un enregistrement de décision d’architecture.

Anti-patrons

La plupart des programmes de microservices qui échouent le font de manière reconnaissable. L’échec le plus grave est le monolithe distribué : un système qui a tous les coûts de la distribution et aucune de ses indépendances, parce que ses services partagent une base de données, s’appellent en longues chaînes synchrones ou dépendent des mêmes bibliothèques déployables.

Anti-patrons des microservices

Anti-patron (anti-pattern)SymptômeCause et remède
Monolithe distribuéLes services doivent être mis en production ensemble dans un ordre fixe ; la panne d’un service les arrête tous.Base de données partagée, chaînes synchrones et bibliothèques déployables partagées. Remède : redessiner les frontières autour des contextes délimités, donner à chaque service ses données, remplacer les appels par des événements, ou fusionner à nouveau en un monolithe modulaire.
Services d’entitésDes services nommés d’après des noms communs (Client, Commande, Restaurant), avec des opérations de création, lecture, mise à jour et suppression ; chaque processus métier en appelle plusieurs.Des frontières tracées autour des données plutôt que du comportement. Michael Nygard appelle cela l’anti-patron du service d’entité (entity service). Remède : s’organiser autour des capacités et des processus métier.
Services bavardsUne seule requête utilisateur provoque des dizaines d’appels entre services ; la latence et les taux de défaillance augmentent à chaque fonctionnalité.Les frontières traversent un flux de travail cohérent, ou les interfaces sont trop fines. Remède : des API à plus gros grain, des copies locales des données de référence, la fusion des services qui changent toujours ensemble.
Bibliothèques partagées qui couplent les déploiementsUn changement dans une bibliothèque commune oblige chaque service à être reconstruit et redéployé ; les versions divergent.Logique métier ou modèles de domaine placés dans du code partagé. Remède : ne partager que des bibliothèques techniques stables ; dupliquer de petites quantités de code métier ; versionner tout ce qui est partagé et permettre l’utilisation de plusieurs versions à la fois.
L’envie de microservicesUne petite équipe avec un nouveau produit démarre avec trente services et passe l’essentiel de son temps sur l’infrastructure.Choisir ce style par effet de mode ou pour le CV plutôt qu’en fonction des facteurs. Remède : commencer par un monolithe modulaire et extraire des services quand un facteur apparaît.
NanoservicesDes services si petits que l’essentiel de leur code est de la plomberie ; une fonctionnalité exige des changements dans cinq d’entre eux.Appliquer « petit » à l’excès. Remède : utiliser les intégrateurs de granularité ; dimensionner les services selon leur cohésion, pas selon les lignes de code.

Caractéristiques des microservices

CaractéristiqueÉvaluationRaison
DéployabilitéÉlevéeChaque service est mis en production seul, plusieurs fois par jour, avec un faible rayon d’impact.
Scalabilité et élasticitéÉlevéeChaque service passe à l’échelle indépendamment ; les petits services démarrent vite et s’ajustent par paliers fins.
Tolérance aux pannesÉlevée (si la conception le prévoit)Les défaillances peuvent être isolées par service, mais seulement avec des délais d’expiration, des cloisonnements, des solutions de repli et une communication asynchrone ; sinon, les fautes se propagent en cascade.
ÉvolutivitéÉlevéeDes services petits et bien délimités peuvent être réécrits ou remplacés individuellement.
Testabilité d’un serviceÉlevéeChaque service est petit ; des tests de contrat vérifient ses interactions.
Tester l’ensembleFaibleLe comportement de bout en bout émerge de nombreux services et il est difficile à reproduire dans un environnement de test.
PerformancesFaible à moyenneLes sauts réseau, la sérialisation et les contrôles de sécurité ajoutent de la latence à chaque interaction.
Cohérence des donnéesFaiblePas de transactions partagées ; les invariants métier qui couvrent plusieurs services reposent sur la cohérence à terme et les sagas.
SimplicitéFaibleDe nombreuses pièces mobiles, de nombreux modes de défaillance, beaucoup d’infrastructure.
Coût globalFaible (coûteux)Plateforme, outillage, observabilité et personnel pour exploiter des dizaines de services.

Quand les microservices conviennent, et quand ils ne conviennent pas

Les microservices conviennent aux organisations dont de nombreuses équipes travaillent sur un même produit et doivent mettre en production indépendamment, aux systèmes dont les parties ont des besoins réellement différents en scalabilité, en disponibilité ou en sécurité, et aux domaines suffisamment bien compris pour tracer des frontières stables. Ils exigent un investissement dans une plateforme et dans les compétences d’exploitation avant même que le premier service soit extrait.

Ils ne conviennent pas à une petite équipe, à un nouveau produit dont le domaine est encore en cours de découverte (des frontières tracées trop tôt coûtent cher à déplacer à travers le réseau), à un système dont les flux de travail centraux exigent une forte cohérence transactionnelle sur la plupart de ses données, ni à une organisation dépourvue de déploiement et de supervision automatisés. Le conseil MonolithFirst de Fowler (chapitre 5) et les retours en arrière que certaines entreprises ont documentés, comme la consolidation en 2018, chez Segment, de plus de 140 services de destination en un seul, montrent que ce style est un outil qui a un coût, pas une destination.

Vérifiez votre compréhension

Deux services sont déployés dans des conteneurs séparés mais doivent toujours être mis en production ensemble. Sont-ils déployables indépendamment ?

Non. La déployabilité indépendante consiste à pouvoir modifier et mettre en production l’un sans l’autre ; un contrat couplé ou une base de données partagée en font une seule unité du point de vue de la mise en production.

Quelle est la différence entre une API gateway et un backend for frontend ?

Une passerelle est un point d’entrée général qui gère des préoccupations transversales comme TLS, l’authentification, la limitation de débit et le routage ; un BFF est un backend propre à un client, qui met en forme les données pour un type de frontend et qui est détenu par l’équipe de ce frontend.

Quel intégrateur de granularité s’oppose le plus fortement au découpage de deux parties qui doivent mettre à jour des données de façon atomique ?

Les transactions de base de données : les découper remplacerait une transaction ACID par un flux de travail distribué tel qu’une saga.

Pourquoi des services nommés Client, Commande et Restaurant, offrant uniquement des opérations de création, lecture, mise à jour et suppression, sont-ils un signal d’alerte ?

Ce sont des services d’entités : des frontières tracées autour des données plutôt que du comportement, si bien que chaque processus métier doit appeler plusieurs services, ce qui crée des interactions bavardes et fortement couplées.

Suivant · 6.4Pilotée par les événementsÉvénements, commandes et messages ; topologies à courtier et à médiateur ; les quatre patrons d’événements de Fowler ; le fonctionnement des partitions, des offsets et des groupes de consommateurs de Kafka ; garanties de livraison, consommateurs idempotents, schémas et files de lettres mortes.Continuer →

Sources et lectures complémentaires

Une question sur cette section ? ArchitectBot, l’assistant d’étude IA du cours, répond d’abord à partir du cours.

Demander : « Nous avons 25 microservices et chaque mise en production exige la coordination de quatre équipes. Comment savoir si nous avons un monolithe distribué, et que devons-nous corriger en premier ? »