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
- Les microservices (Lewis et Fowler, 2014) construisent une application sous forme de petits services, chacun dans son propre processus, organisés autour d’une capacité métier, déployables indépendamment et communiquant par des mécanismes légers.
- Les frontières des services fonctionnent le mieux lorsqu’elles sont alignées sur les contextes délimités et sur les équipes ; des frontières tracées autour de couches techniques ou de tables de base de données produisent des services bavards et fortement couplés.
- La déployabilité indépendante est la propriété qui les définit ; elle repose sur des contrats rétrocompatibles, des tests de contrat et le versionnage, pas seulement sur des conteneurs séparés.
- La base de données par service fait de chaque service son propre quantum, mais remplace les jointures et les transactions par des appels d’API, des événements, des sagas et la cohérence à terme.
- Les patrons de soutien comprennent les passerelles d’API (API gateways), les backends for frontends, la découverte de services et les maillages de services (service meshes) ; chacun résout un vrai problème et ajoute un élément à exploiter.
- La granularité se décide en pesant les désintégrateurs (périmètre, volatilité, scalabilité, tolérance aux pannes, sécurité, extensibilité) face aux intégrateurs (transactions, flux de travail, code partagé, relations entre données).
- Les échecs typiques sont le monolithe distribué, les services d’entités, les services bavards et les bibliothèques partagées qui couplent les déploiements ; ce style exige de l’automatisation, de la supervision et des équipes qui exploitent ce qu’elles construisent.
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
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
| Patron | Problème résolu | Ce que c’est | Points 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 services | Les 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
Désintégrateurs et intégrateurs de granularité, avec des exemples tirés de la livraison de repas
| Force | Sens | Question à poser | Exemple |
|---|---|---|---|
| Périmètre et fonction | Découper | Le 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écouper | Une 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ébit | Découper | Les 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 pannes | Découper | Une 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écouper | Les 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écouper | De nouvelles variantes seront-elles ajoutées souvent ? | De nouveaux moyens de paiement tous les quelques mois, chacun déployable séparément. |
| Transactions de BD | Garder ensemble | Ces 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égraphie | Garder ensemble | Le 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 ensemble | Les 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ées | Garder ensemble | Les 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écision | Dé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ôme | Cause 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és | Des 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 bavards | Une 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éploiements | Un 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 microservices | Une 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. |
| Nanoservices | Des 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 | Évaluation | Raison |
|---|---|---|
| Déployabilité | Élevée | Chaque service est mis en production seul, plusieurs fois par jour, avec un faible rayon d’impact. |
| Scalabilité et élasticité | Élevée | Chaque 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ée | Des services petits et bien délimités peuvent être réécrits ou remplacés individuellement. |
| Testabilité d’un service | Élevée | Chaque service est petit ; des tests de contrat vérifient ses interactions. |
| Tester l’ensemble | Faible | Le comportement de bout en bout émerge de nombreux services et il est difficile à reproduire dans un environnement de test. |
| Performances | Faible à moyenne | Les sauts réseau, la sérialisation et les contrôles de sécurité ajoutent de la latence à chaque interaction. |
| Cohérence des données | Faible | Pas de transactions partagées ; les invariants métier qui couvrent plusieurs services reposent sur la cohérence à terme et les sagas. |
| Simplicité | Faible | De nombreuses pièces mobiles, de nombreux modes de défaillance, beaucoup d’infrastructure. |
| Coût global | Faible (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.
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 ? »