Be Software Architecture Wise
Be Wise Apps

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

Chapitre 6 sur 12 · Intermédiaire à avancé

Styles architecturaux II : systèmes distribués

Ce chapitre fait passer l’architecture à travers le réseau. Il explique quand la distribution d’un système vaut son coût, les illusions qui la rendent plus difficile qu’il n’y paraît, et les principaux styles distribués : l’architecture à base de services, l’architecture orientée services, les microservices, l’architecture pilotée par les événements, le serverless et l’architecture basée sur l’espace. Il traite ensuite des mécanismes dont ils dépendent tous : la communication synchrone et asynchrone et la conception d’API, les modèles de cohérence et le théorème CAP, ainsi que les transactions distribuées avec les sagas et le patron outbox. Il s’adresse aux développeurs et aux architectes qui conçoivent ou évaluent des systèmes composés de nombreux services, et il se montre précis sur les défaillances, les garanties de livraison et la cohérence.

Introduction vidéo au chapitre 6

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

Bienvenue dans le chapitre 6 : Styles architecturaux, deuxième partie, systèmes distribués. Le chapitre 5 a décrit des styles dans lesquels l’ensemble du système est déployé comme une seule unité. Ce chapitre pose les mêmes questions à travers un réseau. Il explique quand la distribution d’un système vaut son coût, quels sont les principaux styles distribués, et de quels mécanismes ils dépendent tous. Et il se montre précis sur les défaillances, les garanties de livraison et la cohérence.

Presque tous les systèmes d’une certaine taille sont aujourd’hui distribués d’une manière ou d’une autre. Une application mobile dialogue avec des services backend, qui appellent des prestataires de paiement, des services de cartographie et des courtiers de messages, et les services eux-mêmes tournent sur de nombreuses machines. Découper un système peut apporter une mise à l’échelle indépendante, l’isolation des pannes, des mises en production indépendantes et des équipes autonomes. Cela apporte aussi des problèmes qui ne peuvent pas se produire à l’intérieur d’un seul processus : des messages perdus ou dupliqués, des services lents plutôt que morts, des données qui divergent d’une copie à l’autre, et des pannes sur des machines dont vous ignoriez dépendre.

Le chapitre est de niveau intermédiaire à avancé. Il s’adresse aux développeurs et aux architectes qui conçoivent ou évaluent des systèmes composés de nombreux services. Il s’appuie sur les styles du chapitre 5 et les qualités du chapitre 2, désormais soumis aux conditions du réseau. En particulier, il utilise la disponibilité en série et en parallèle, le couplage et la loi de Conway, ainsi que le quantum d’architecture, le monolithe modulaire et les contextes délimités. Et il mène au chapitre 7, qui traite de la partie la plus difficile de la distribution : les données.

L’idée la plus importante du chapitre est que la distribution est un échange, pas une amélioration. Chaque avantage se paie en latence, en cohérence, en observabilité et en effort d’exploitation. Un bon architecte sait dire quel avantage est acheté, à quel prix, et pourquoi une option moins chère à l’intérieur d’un monolithe ne suffit pas.

Le chapitre va du pourquoi au comment. La section six point un expose les raisons de distribuer, les huit illusions de l’informatique distribuée et la défaillance partielle, et vous donne l’arithmétique nécessaire pour évaluer le prix de l’échange avant de vous y engager. La section six point deux traite de l’architecture à base de services, un juste milieu pragmatique composé de quelques services de domaine à gros grain, et de l’architecture orientée services classique, y compris les raisons de sa disgrâce. La section six point trois traite des microservices : des services alignés sur les contextes délimités, le déploiement indépendant, une base de données par service, la manière de décider de la taille d’un service, et le monolithe distribué. La section six point quatre traite de l’architecture pilotée par les événements : événements et commandes, courtiers et médiateurs, garanties de livraison, et consommateurs capables de recevoir sans risque deux fois le même message.

Voici l’arithmétique de la section six point un. Passer une commande traverse cinq services : l’API gateway, puis les commandes, la carte, la tarification et le paiement. Chacun attend la réponse du suivant, et chacun, pris isolément, est disponible quatre-vingt-dix-neuf virgule neuf pour cent du temps. Mais les disponibilités se multiplient. Ensemble, elles donnent un chemin de requête à environ quatre-vingt-dix-neuf virgule cinq pour cent seulement : environ trois virgule six heures d’indisponibilité par mois. Et les latences s’additionnent. Avec vingt millisecondes de travail dans chaque service, plus un peu pour chaque saut réseau, la médiane est d’environ cent dix millisecondes. Cinq services respectables chacun pris isolément ont produit un chemin de requête bien plus faible. Voilà le prix de la distribution, calculé sur le papier avant de construire quoi que ce soit.

Ce diagramme montre la défaillance partielle, le problème qui définit le domaine. Un service des commandes demande à un service de paiement d’autoriser vingt-quatre livres cinquante, et attend la réponse. Trois choses différentes peuvent mal tourner. La requête est perdue, et aucun débit n’a eu lieu. Le service de paiement plante ou se bloque, et personne ne le sait. Ou bien la réponse est perdue, et la carte a été débitée. Pour l’appelant, les trois cas sont identiques : aucune réponse avant l’expiration du délai. Toute opération susceptible d’être retentée doit donc être idempotente, c’est-à-dire que l’effectuer deux fois a le même effet que l’effectuer une fois.

La seconde moitié se tourne vers les mécanismes dont dépend tout style distribué. La section six point cinq compare la communication synchrone et asynchrone et le couplage que crée chacune, et traite de la conception d’API, du versionnage et des tests de contrat. La section six point six porte sur ce que peuvent attendre les lecteurs de données copiées : les modèles de cohérence, ce que dit réellement le théorème CAP, et PACELC. La section six point sept explique pourquoi on évite la validation en deux phases entre services, et comment les sagas, les transactions compensatoires et le patron outbox maintiennent la justesse des processus métier sans elle. La section six point huit conclut avec deux styles adaptés à des profils de charge particuliers : les fonctions serverless, qui descendent à zéro, et l’architecture basée sur l’espace, qui garde les données en mémoire pour survivre à des pics extrêmes, comme l’ouverture d’une billetterie.

Trois habitudes traversent toutes les sections. Premièrement, comptez les dépendances synchrones, pas les services. Le nombre d’éléments qui doivent tous fonctionner au même moment pour qu’une requête aboutisse détermine sa disponibilité et sa latence. Deuxièmement, partez du principe que les messages sont perdus, retardés, dupliqués et réordonnés, et concevez les récepteurs de sorte qu’un message répété ne fasse aucun dégât. Troisièmement, décidez à qui appartient chaque donnée, car la propriété détermine où les transactions sont possibles, et où la cohérence doit être gérée entre services. Le chapitre 7 développe cette habitude en un traitement complet de l’architecture des données.

Si vous découvrez le sujet, lisez d’abord le résumé d’ouverture de chaque section et les encadrés intitulés Si vous débutez. Les ingénieurs expérimentés trouveront de la précision là où elle compte. La lecture du chapitre prend environ trois heures et demie. Deux exemples reviennent. La plateforme de livraison de repas illustre une conception distribuée ordinaire. Un système de billetterie pour une tournée des stades montre ce qui change quand des dizaines de milliers de personnes veulent les mêmes quelques places à la même seconde. Chaque section se termine par quelques questions d’autoévaluation. Répondez-y de tête avant de regarder. Quand vous serez prêt, passez le test facultatif du chapitre : vingt questions à choix multiples et deux réponses rédigées, en quarante-cinq minutes environ. La note de réussite est de quatre-vingts pour cent.

Voilà la carte du chapitre 6. Commencez par la section six point un, où nous mettons en balance les raisons de distribuer et les illusions qui rendent la distribution plus difficile qu’il n’y paraît. À très vite.

Télécharger le chapitre (PDF)Lire dans l’application

En un coup d’œil

Vous apprendrez à

  • Expliquer les raisons légitimes de distribuer un système et les coûts qu’entraîne chacune d’elles.
  • Décrire les huit illusions de l’informatique distribuée et la défaillance partielle, et concevoir des réponses à y apporter.
  • Calculer la disponibilité et la latence d’une chaîne d’appels synchrones, et proposer des changements qui les améliorent.
  • Comparer l’architecture à base de services, la SOA classique et les microservices, et choisir entre elles pour une organisation donnée.
  • Décider de la granularité des services en mettant en balance les facteurs de désintégration et d’intégration, et reconnaître le monolithe distribué.
  • Distinguer événements, commandes et messages, topologies à courtier et à médiateur, et les quatre patrons d’événements de Fowler.
  • Expliquer les garanties de livraison, pourquoi « exactement une fois » demande une définition rigoureuse, et comment fonctionnent les consommateurs idempotents.
  • Choisir les styles de communication, les niveaux de cohérence et les patrons de transaction (sagas, outbox) pour les workflows distribués.

Avant de commencer

Les chapitres 0 à 5, en particulier la disponibilité en série et en parallèle (chapitre 2, section 2.5), le couplage et la loi de Conway (chapitre 3), ainsi que le quantum d’architecture, le monolithe modulaire et les contextes délimités (chapitre 5).

Durée

Environ 3 h 30 de lecture ; 45 minutes pour le test.

Termes clés

système distribué · défaillance partielle · illusions de l’informatique distribuée · couplage temporel · architecture à base de services · bus de services d’entreprise · microservices · déployabilité indépendante · base de données par service · architecture pilotée par les événements · livraison au moins une fois (at-least-once) · consommateur idempotent · Théorème CAP · saga

Pourquoi ce chapitre compte

Le chapitre 5 a décrit des styles dans lesquels l’ensemble du système est déployé comme une seule unité. Ce chapitre pose les mêmes questions à travers un réseau. Presque tous les systèmes d’une certaine taille sont aujourd’hui distribués d’une manière ou d’une autre : une application mobile dialogue avec des services backend, qui appellent des prestataires de paiement, des services de cartographie et des courtiers de messages, et les services eux-mêmes tournent sur de nombreuses machines. Découper un système peut apporter une mise à l’échelle indépendante, l’isolation des pannes, des mises en production indépendantes et des équipes autonomes. Cela apporte aussi une catégorie de problèmes qui ne peuvent pas se produire à l’intérieur d’un seul processus : des messages perdus ou dupliqués, des services lents plutôt que morts, des données qui divergent d’une copie à l’autre, et des pannes sur des machines dont vous ignoriez dépendre.

L’idée la plus importante à retenir est que la distribution est un échange, pas une amélioration. Chaque avantage se paie en latence, en cohérence, en observabilité et en effort d’exploitation, et un bon architecte sait dire quel avantage est acheté, à quel prix, et pourquoi une option moins chère à l’intérieur d’un monolithe ne suffit pas. Les illusions de l’informatique distribuée et l’arithmétique des chaînes d’appels synchrones présentées dans la première section sont les outils qui permettent d’évaluer le prix de cet échange avant de s’y engager.

Comment les sections s’articulent

Le chapitre va du pourquoi au comment. La section 6.1 expose les raisons de distribuer, les huit illusions, la défaillance partielle et les coûts, et montre par un exemple commenté comment cinq services qui atteignent chacun 99,9 % de disponibilité donnent un chemin de requête à environ 99,5 % seulement. Elle se termine en revenant sur le quantum d’architecture, qui explique pourquoi les appels synchrones lient entre eux des services déployés séparément.

Les trois sections suivantes présentent les principaux styles distribués, chacun traité comme les styles du chapitre 5 : définition et origine, diagramme, fonctionnement, exemple, tableau des caractéristiques, quand l’utiliser et les anti-patrons habituels. La section 6.2 traite de l’architecture à base de services, un juste milieu pragmatique composé de quelques services de domaine à gros grain qui partagent souvent une base de données, et de l’architecture orientée services classique, avec ses bus de services d’entreprise et ses modèles canoniques, y compris les raisons de sa disgrâce. La section 6.3 traite des microservices : des services alignés sur les contextes délimités, la déployabilité indépendante, la base de données par service, les patrons d’appui comme les API gateways et les service meshes, la manière de choisir la granularité, ainsi que le monolithe distribué et d’autres anti-patrons. La section 6.4 traite de l’architecture pilotée par les événements : événements et commandes, topologies à courtier et à médiateur, partitions et groupes de consommateurs de Kafka, garanties de livraison et consommateurs idempotents.

La seconde moitié se tourne vers les mécanismes dont dépend tout style distribué. La section 6.5 compare la communication synchrone et asynchrone et le couplage que crée chacune, et traite de REST, gRPC, GraphQL et de la messagerie, des bonnes pratiques de conception d’API, du versionnage et des tests de contrat. La section 6.6 porte sur ce que peuvent attendre les lecteurs de données répliquées : les modèles de cohérence, de la linéarisabilité à la cohérence à terme, le théorème CAP et ce qu’il dit réellement, PACELC et les quorums. La section 6.7 explique pourquoi on évite la validation en deux phases entre services et comment les sagas, les transactions compensatoires et l’outbox transactionnelle maintiennent la justesse des processus métier sans elle. La section 6.8 conclut avec deux styles adaptés à des profils de charge particuliers : les fonctions serverless, qui descendent à zéro et sont facturées à l’invocation, et l’architecture basée sur l’espace, qui garde les données en mémoire pour survivre à des pics extrêmes comme l’ouverture d’une billetterie.

Les exemples récurrents et comment lire le chapitre

Deux exemples reviennent. La plateforme de livraison de repas des chapitres précédents (clients, restaurants, livreurs, paiements) illustre une conception distribuée ordinaire : elle apparaît sous la forme de cinq services de domaine, d’un ensemble de microservices, d’un flux d’événements OrderPlaced et d’une saga de commande. Un système de billetterie qui vend des places pour la tournée des stades d’un artiste montre ce qui change sous une charge extrême et en pics, quand des dizaines de milliers de personnes veulent les mêmes quelques places à la même seconde.

Le chapitre est de niveau intermédiaire à avancé. Il suppose acquis les chapitres 0 à 5, en particulier la disponibilité en série et en parallèle (chapitre 2), le couplage et la loi de Conway (chapitre 3), ainsi que le quantum d’architecture, le monolithe modulaire et les contextes délimités (chapitre 5). Les débutants peuvent lire d’abord le résumé d’ouverture de chaque section et les encadrés « Si vous débutez ». Les ingénieurs expérimentés trouveront de la précision là où elle compte : ce qu’implique une livraison au moins une fois (at-least-once) pour chaque consommateur, ce que « exactement une fois » signifie et ne signifie pas, et pourquoi la cohérence à terme doit être prise en compte dès la conception plutôt que simplement tolérée.

Ce qu’il faut retenir pour la suite

Trois habitudes traversent toutes les sections. Premièrement, comptez les dépendances synchrones, pas les services : le nombre d’éléments qui doivent tous fonctionner au même moment pour que la requête d’un utilisateur aboutisse détermine la disponibilité et la latence. Deuxièmement, partez du principe que les messages sont perdus, retardés, dupliqués et réordonnés, et concevez des récepteurs idempotents. Troisièmement, décidez à qui appartient chaque donnée, car la propriété détermine où les transactions sont possibles et où la cohérence doit être gérée entre services. Le chapitre 7 développe cette troisième habitude en un traitement complet de l’architecture des données.

Les 8 sections

6.1 · Intermédiaire · 24 minPourquoi distribuerLes vraies raisons de répartir un système sur plusieurs machines, les huit illusions qui rendent la distribution plus difficile qu’il n’y paraît, la défaillance partielle, les coûts et l’arithmétique des chaînes d’appels synchrones.Lire →6.2 · Intermédiaire · 22 minArchitecture à base de services et SOADes services de domaine à gros grain partageant une base de données, l’ère du bus de services d’entreprise de la SOA et les raisons de son déclin, ce qui distingue les microservices, et quand l’architecture à base de services constitue un juste milieu pragmatique.Lire →6.3 · Avancé · 26 minMicroservicesCe que sont les microservices selon Lewis et Fowler, les contextes délimités, la déployabilité indépendante, la base de données par service, les passerelles et les maillages de services, comment décider de la granularité, les anti-patrons classiques et le prix organisationnel.Lire →6.4 · Avancé · 28 minPiloté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.Lire →6.5 · Intermédiaire · 30 minCommunication et APIComment les services dialoguent : le couplage créé par la communication synchrone et asynchrone, la sémantique de REST et de HTTP, gRPC, GraphQL et la messagerie, et les pratiques de conception d’API qui permettent aux interfaces d’évoluer sans casser les consommateurs.Lire →6.6 · Avancé · 30 minCAP et cohérenceCe que signifie la cohérence pour des données répliquées : les modèles, de la linéarisabilité à la cohérence à terme, ce que le théorème CAP dit réellement et ce qu’il ne dit pas, le compromis quotidien sur la latence mis en évidence par PACELC, l’arithmétique des quorums et le choix de la cohérence selon le cas d’usage.Lire →6.7 · Avancé · 30 minSagasComment garder les données cohérentes quand une action métier s’étend sur plusieurs services : la validation en deux phases et pourquoi on l’évite, les sagas avec compensations, chorégraphie et orchestration, les contre-mesures d’isolation, l’outbox transactionnelle et les récepteurs idempotents.Lire →6.8 · Intermédiaire · 28 minServerless et basée sur l’espaceDeux réponses opposées à la question de la capacité : les fonctions serverless et les backends managés, qui descendent à zéro et sont facturés à l’usage, et l’architecture basée sur l’espace, qui absorbe des pics extrêmes depuis une mémoire répliquée en tenant la base de données à l’écart du chemin critique.Lire →

Test du chapitre

Vérifiez votre compréhension du chapitre 6

Facultatif : 20 questions à choix multiples et 2 courtes réponses rédigées, tirées à chaque fois d’une banque de 72 questions. Note de réussite : 80 %. Réussir tous les tests de chapitre, puis l’évaluation finale, donne droit au Certificat de fin de formation Be Wise.

Passer le test du chapitre 6 dans l’app

Lectures complémentaires