Be Software Architecture Wise
Be Wise Apps

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

Chapitre 9 sur 12 · Intermédiaire à avancé

Performances, scalabilité, résilience et exploitabilité

Ce chapitre transforme les scénarios de performances et de disponibilité du chapitre 2 en systèmes qui fonctionnent. Il traite de la scalabilité verticale et horizontale et du cube de scalabilité, de l’équilibrage de charge et des services sans état, des files d’attente, du back pressure et de la limitation de débit, des patrons de résilience qui empêchent les défaillances de se propager (délais d’expiration, nouvelles tentatives, disjoncteurs, cloisonnement), des SLI, des SLO et des budgets d’erreur, de l’observabilité avec les journaux, les métriques et les traces, de la planification de la capacité et des tests de performances, ainsi que de l’ingénierie du chaos et de l’apprentissage tiré des incidents. Il s’adresse aux développeurs et aux architectes qui connaissent les styles distribués du chapitre 6 et qui doivent garder un système rapide et opérationnel sous une charge réelle.

Introduction vidéo au chapitre 9

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

Bienvenue dans le chapitre 9 : Performances, scalabilité, résilience et exploitabilité. Une conception qui atteint ses objectifs sur un diagramme peut tout de même s’effondrer un vendredi à midi et demi, quand tous les bureaux de la ville commandent leur déjeuner. La différence tient rarement à du code astucieux. Elle tient à un ensemble de décisions architecturales : comment la capacité est ajoutée, comment la charge est répartie, comment le travail attend, comment les défaillances sont contenues, et comment les personnes qui exploitent le système savent ce qu’il fait.

Ce chapitre s’adresse aux développeurs et aux architectes qui connaissent les styles distribués du chapitre 6, et qui doivent garder un système rapide et opérationnel sous une charge réelle. Il s’appuie sur le chapitre 2, qui a rendu précises les performances et la disponibilité sous forme de scénarios d’attribut de qualité testables. Vous apprendrez ici à atteindre ces scénarios dans un système en fonctionnement, et à les garder vrais le jour le plus chargé de l’année. Il renvoie au chapitre 7 pour la réplication, le partitionnement et la mise en cache, plutôt que de les répéter. Et il mène au chapitre 10, consacré aux plateformes cloud, aux fonctionnalités de Kubernetes et aux conceptions multirégions sur lesquelles ces systèmes tournent généralement.

Deux exemples récurrents traversent le chapitre. Une plateforme de livraison de repas, avec des pics marqués à midi et le soir. Et une mise en vente de billets, où la demande passe de presque rien à plusieurs fois la capacité du système en quelques secondes. La section neuf point un compare la scalabilité verticale et la scalabilité horizontale, utilise le cube de scalabilité pour distinguer le clonage, le découpage par fonction et le découpage par données, et explique pourquoi l’autoscaling sur le CPU est souvent un mauvais choix. La section neuf point deux traite de ce qui se trouve devant les instances : les équilibreurs de charge, les algorithmes qu’ils utilisent, les contrôles de santé, le drainage des connexions, et les raisons pour lesquelles les sessions persistantes doivent céder la place à un état de session conservé hors de l’instance. La section neuf point trois porte sur ce qui se passe quand le travail arrive plus vite qu’il ne peut être fait : files bornées, back pressure, délestage de charge et limitation de débit, qui décident de ce qui est accepté, de ce qui attend et de ce qui est refusé poliment. La section neuf point quatre traite des défaillances entre services : délais d’expiration et échéances, nouvelles tentatives avec backoff et jitter, disjoncteurs, cloisonnement et solutions de repli.

L’exemple commenté de la section neuf point quatre montre comment un seul délai d’expiration manquant permet à une seule dépendance lente de faire tomber tout ce qui l’appelle. Le prestataire de paiement répond normalement en zéro virgule trois seconde. Aujourd’hui, il ne répond plus. Le service de commandes l’appelle sans délai d’expiration, si bien que, un par un, ses deux cents threads finissent tous par attendre des appels de paiement. Alors l’étape de paiement échoue. Mais l’historique des commandes et le suivi échouent aussi, alors qu’ils ne touchent jamais aux paiements, parce qu’il ne reste plus aucun thread libre pour les servir. La base de données est en parfaite santé, mais aucun thread n’est libre pour l’appeler. Les délais d’expiration, les disjoncteurs et le cloisonnement sont les patrons qui arrêtent ce type de cascade.

La seconde moitié passe des mécanismes à l’exploitation. La section neuf point cinq montre comment exprimer la fiabilité du point de vue de l’utilisateur, et comment un budget d’erreur transforme un objectif de disponibilité en une quantité de défaillances autorisées que les équipes peuvent dépenser en changements. La section neuf point six traite des journaux, des métriques et des traces qui permettent aux ingénieurs de poser de nouvelles questions à un système en production, ainsi que du traçage distribué avec OpenTelemetry. La section neuf point sept boucle la boucle entre prévisions et preuves, avec les tests de charge, de stress, d’endurance, de pic et de point de rupture, et un plan de capacité pour une mise en vente de billets. Et la section neuf point huit traite des défaillances qui surviennent malgré tout : des expériences délibérées pour trouver les faiblesses avant les clients, des rôles clairs pendant les incidents, et des revues sans reproche qui changent le système plutôt que les personnes.

Ce diagramme de la section neuf point cinq place trois termes sur une même échelle, à partir de la disponibilité de l’étape de paiement sur une fenêtre glissante de vingt-huit jours. L’objectif de niveau de service, ou SLO, est la cible interne : ici, quatre-vingt-dix-neuf virgule neuf pour cent. L’accord de niveau de service, ou SLA, est un contrat avec les partenaires, fixé moins haut, à quatre-vingt-dix-neuf virgule cinq pour cent. L’indicateur de niveau de service, ou SLI, est la mesure. Ce mois-ci, il est de quatre-vingt-dix-neuf virgule quatre-vingt-quatorze pour cent, dans la zone où le service reste dans son budget. En dessous du SLO, l’objectif est manqué, et une politique de budget d’erreur écrite indique ce qui se passe ensuite. Ce n’est qu’en dessous du SLA que des crédits de service sont dus. L’écart entre le SLO et le SLA est la zone d’alerte. Le budget d’erreur est simplement un moins le SLO. Sur trente jours, un objectif de quatre-vingt-dix-neuf virgule neuf pour cent autorise quarante-trois virgule deux minutes de panne totale, soit une requête sur mille en échec.

Les sections forment une chaîne, et elles mènent à une idée. Toute ressource est finie, donc tout système a un point de rupture. Le travail de l’architecte est de décider à l’avance de ce qui se passe quand il est atteint. Un système bien conçu soumis à une charge excessive ralentit en douceur, et se déleste d’abord du travail le moins important. Il refuse clairement, plutôt que d’expirer en silence. Il isole la partie défaillante. Et il se rétablit de lui-même quand la pression retombe. Un système mal conçu met en file sans limite, réessaie jusqu’à s’effondrer, et entraîne ses voisins dans sa chute. Ces mécanismes coûtent peu à ajouter lors de la conception, et cher à ajouter après coup. Qu’un service soit sans état, qu’une file soit bornée et qu’une requête porte une échéance, tout cela se décide bien avant le premier incident.

À la fin du chapitre, vous saurez choisir comment passer à l’échelle, et dimensionner un parc pour un pic connu avec la loi de Little et une marge de capacité. Vous saurez combiner délais d’expiration, échéances, nouvelles tentatives avec backoff et jitter, disjoncteurs, cloisonnement et solutions de repli pour contenir les défaillances. Vous saurez définir des indicateurs et des objectifs de niveau de service du point de vue de l’utilisateur, calculer des budgets d’erreur, et concevoir des alertes sur la vitesse à laquelle ils sont consommés. Et vous saurez planifier la capacité et les tests de performances, mener des expériences de chaos en toute sécurité, et animer des revues post-incident sans reproche.

Comme les sections forment une chaîne, mieux vaut les lire dans l’ordre. Mais chacune se suffit aussi à elle-même, et vous pouvez donc aller directement à la section dont vous avez besoin. Comptez environ trois heures et demie pour lire tout le chapitre. À la fin de chaque section, vous trouverez des questions d’autoévaluation. Répondez-y de tête avant de regarder les réponses. Quand vous serez prêt, un test facultatif du chapitre vous attend, qui dure environ quarante-cinq minutes. Il comporte vingt questions à choix multiples et deux réponses rédigées. La note de réussite est de quatre-vingts pour cent.

Voilà comment le chapitre est construit. Commencez par la section neuf point un, sur la scalabilité verticale, la scalabilité horizontale et le cube de scalabilité. À très vite.

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

En un coup d’œil

Vous apprendrez à

  • Choisir entre scalabilité verticale et horizontale, et entre les axes X, Y et Z du cube de scalabilité, et dimensionner un parc de serveurs pour un pic connu à l’aide de la loi de Little et d’une marge de capacité.
  • Choisir des signaux et des réglages d’autoscaling qui évitent le décalage et les oscillations (flapping), et expliquer pourquoi le CPU est souvent la mauvaise métrique.
  • Comparer l’équilibrage de charge de couche 4 et de couche 7 ainsi que les principaux algorithmes, concevoir les contrôles de santé et le drainage des connexions, et externaliser l’état de session.
  • Appliquer les files d’attente, les tampons bornés, le back pressure, le délestage de charge et la limitation de débit (y compris le token bucket) pour garder la surcharge sous contrôle.
  • Combiner délais d’expiration, échéances, nouvelles tentatives avec backoff et jitter, budgets de nouvelles tentatives, disjoncteurs, cloisonnement et solutions de repli pour contenir les défaillances.
  • Définir des SLI et des SLO du point de vue de l’utilisateur, calculer les budgets d’erreur et les taux de consommation, et concevoir des alertes qui s’appuient sur eux.
  • Instrumenter un système avec des journaux, des métriques et des traces à l’aide d’OpenTelemetry, et utiliser les méthodes RED et USE pour diagnostiquer les problèmes.
  • Planifier la capacité et les tests de performances, mener des expériences de chaos en toute sécurité et animer des revues post-incident sans reproche.

Avant de commencer

Le chapitre 2, en particulier les sections sur les performances et la scalabilité et sur la disponibilité et la fiabilité ; le chapitre 6, en particulier « Pourquoi distribuer » et « Communication et API » ; et les sections du chapitre 7 sur la réplication, le partitionnement et la mise en cache.

Durée

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

Termes clés

cube de scalabilité · autoscaling · service sans état · équilibreur de charge de couche 7 · puissance de deux choix aléatoires · back pressure (contre-pression) · délestage de charge · token bucket (seau à jetons) · disjoncteur (circuit breaker) · cloisonnement (bulkhead) · budget d’erreur · taux de consommation (burn rate) · traçage distribué · ingénierie du chaos

Des qualités sur le papier aux qualités en production

Le chapitre 2 a rendu précises les performances et la disponibilité : percentiles de latence, débit, loi de Little, taux d’utilisation et « neuf », formulés sous forme de scénarios d’attribut de qualité testables. Ce chapitre porte sur la manière d’atteindre ces scénarios dans un système en fonctionnement et de les garder vrais le jour le plus chargé de l’année. Une conception qui atteint ses objectifs sur un diagramme peut tout de même s’effondrer un vendredi à 12 h 30, quand tous les bureaux de la ville commandent leur déjeuner, ou à 10 h 00 le matin où les billets d’un concert sont mis en vente. La différence entre les deux tient rarement à du code astucieux. Elle tient à un ensemble de décisions architecturales : comment la capacité est ajoutée, comment la charge est répartie, comment le travail attend, comment les défaillances sont contenues, et comment les personnes qui exploitent le système savent ce qu’il fait.

Deux exemples récurrents traversent le chapitre. La plateforme de livraison de repas connaît chaque jour un pic marqué à midi et le soir, compte des dizaines de services et dépend de tiers comme les prestataires de paiement et les API de cartographie. La mise en vente de billets est le cas extrême : une demande qui passe de presque rien à plusieurs fois la capacité du système en quelques secondes, pour un stock fixe de places, sous les yeux de tout le pays. À eux deux, ils mettent en jeu toutes les techniques du chapitre.

Gérer la charge : passage à l’échelle, équilibrage et attente

Les quatre premières sections portent sur la charge. Stratégies de passage à l’échelle compare la scalabilité verticale et la scalabilité horizontale, utilise le cube de scalabilité d’Abbott et Fisher pour distinguer le clonage, le découpage par fonction et le découpage par données, et explique pourquoi l’autoscaling sur le CPU est souvent un mauvais choix et comment dimensionner un parc pour un pic connu avec la loi de Little et une marge de capacité. Équilibrage de charge, absence d’état et sessions traite de ce qui se trouve devant les instances : les équilibreurs de charge de couche 4 et de couche 7, les algorithmes qu’ils utilisent (dont la puissance de deux choix aléatoires), des contrôles de santé qui ne retirent pas tout un parc d’un coup, le drainage des connexions, et les raisons pour lesquelles les sessions persistantes doivent céder la place à un état de session externalisé.

Asynchronisme, files d’attente et back pressure traite de ce qui se passe quand le travail arrive plus vite qu’il ne peut être fait. Les files d’attente transforment les pics en arriérés, ce qui n’est utile que si l’arriéré est borné et se résorbe dans un délai acceptable. Le back pressure, le délestage de charge et la limitation de débit décident quel travail est accepté, lequel attend et lequel est refusé poliment avec un HTTP 429. Délais d’expiration, nouvelles tentatives, disjoncteurs, cloisonnement et dégradation gracieuse traite ensuite des défaillances entre services : délais d’expiration et échéances, nouvelles tentatives avec backoff et jitter et budgets qui empêchent les tempêtes de nouvelles tentatives, disjoncteurs, cloisonnement, solutions de repli, idempotence et requêtes de couverture. Son exemple commenté montre comment un seul délai d’expiration manquant permet à une seule dépendance lente de faire tomber tout ce qui l’appelle.

Exploiter le système : objectifs, observabilité, tests et apprentissage

La seconde moitié passe des mécanismes à l’exploitation. SLI, SLO, SLA et budgets d’erreur montre comment exprimer la fiabilité du point de vue de l’utilisateur, comment un budget d’erreur transforme un objectif de disponibilité en une quantité de défaillances autorisées que les équipes peuvent dépenser en changements, et comment les alertes sur le taux de consommation ne sollicitent les personnes d’astreinte que lorsque ce budget est réellement menacé. Observabilité traite des journaux, des métriques et des traces qui permettent aux ingénieurs de poser de nouvelles questions à un système en production, des méthodes RED et USE et des quatre signaux d’or, du traçage distribué avec OpenTelemetry, et du coût des données à forte cardinalité.

Planification de la capacité et tests de performances boucle la boucle entre prévisions et preuves : tests de charge, de stress, d’endurance, de pic et de point de rupture, modèles de charge ouverts et fermés, omission coordonnée, et un plan de capacité pour une mise en vente de billets. Ingénierie du chaos, incidents et apprentissage sans reproche traite des défaillances qui surviennent malgré tout : expérimenter délibérément en production pour trouver les faiblesses avant les clients, gérer les incidents avec des rôles clairs, et mener des revues sans reproche dont les actions correctives changent le système plutôt que les personnes.

Comment les sections s’articulent

Les sections forment une chaîne. Le passage à l’échelle et l’équilibrage de charge ajoutent de la capacité ; les files d’attente et le back pressure décident de ce qui se passe quand la capacité vient malgré tout à manquer ; les patrons de résilience empêchent un problème local de devenir global. Les SLO disent ce qui est assez bon, l’observabilité montre si le système atteint ce niveau et, sinon, pourquoi, les tests et la planification de la capacité prédisent quand il cessera de l’atteindre, et l’ingénierie du chaos et les revues d’incident trouvent les lacunes de tout ce qui précède. La plupart de ces mécanismes coûtent peu à ajouter lors de la conception et cher à ajouter après coup ; c’est pourquoi ils relèvent de l’architecture plutôt que du détail d’exploitation : qu’un service soit sans état, qu’un appel soit idempotent, qu’une file soit bornée et qu’une requête porte une échéance, tout cela se décide bien avant le premier incident.

Le chapitre suppose connus les styles distribués du chapitre 6 et l’architecture des données du chapitre 7. Il y renvoie pour les clés d’idempotence, les garanties de livraison, la réplication et la mise en cache plutôt que de les répéter, et renvoie au chapitre 10 pour les plateformes cloud, les fonctionnalités de Kubernetes et les conceptions multirégions sur lesquelles ces systèmes tournent généralement.

L’idée à retenir

Toute ressource est finie, donc tout système a un point de rupture ; le travail de l’architecte est de décider à l’avance de ce qui se passe quand il est atteint. Un système bien conçu soumis à une charge excessive ralentit en douceur, se déleste d’abord du travail le moins important, refuse clairement plutôt que d’expirer en silence, isole la partie défaillante et se rétablit de lui-même quand la pression retombe. Un système mal conçu met en file sans limite, réessaie jusqu’à s’effondrer et entraîne ses voisins dans sa chute. La différence tient à de petits choix délibérés (un délai d’expiration ici, une file bornée là, un budget de nouvelles tentatives, une sonde de disponibilité) et à l’habitude de mesurer, de tester et d’apprendre du système tel qu’il fonctionne réellement.

Les 8 sections

9.1 · Intermédiaire · 28 minPassage à l’échelleLa scalabilité verticale et horizontale et leurs limites, le cube de scalabilité d’Abbott et Fisher, l’absence d’état, l’autoscaling réactif, planifié et prédictif, le choix d’un signal de mise à l’échelle, comment éviter le flapping, et le dimensionnement d’un parc de serveurs pour un pic.Lire →9.2 · Intermédiaire · 27 minÉquilibrage de chargeLes équilibreurs de charge de couche 4 et de couche 7, les principaux algorithmes, dont la puissance de deux choix aléatoires, les contrôles de vivacité et de disponibilité, le drainage des connexions, les inconvénients des sessions persistantes, l’état de session externalisé et l’équilibrage de charge global.Lire →9.3 · Intermédiaire · 29 minFiles d’attente et back pressureComment les files d’attente transforment les pics en arriérés, les consommateurs concurrents, le dimensionnement des files avec la loi de Little, le back pressure, le délestage de charge et la priorisation, le token bucket et les autres limiteurs de débit, HTTP 429 avec Retry-After, et les files de lettres mortes.Lire →9.4 · Avancé · 32 minPatrons de résilienceLes patrons de stabilité qui empêchent une seule dépendance lente de faire tomber un système : délais d’expiration et échéances, nouvelles tentatives avec backoff, jitter et budgets, disjoncteurs, cloisonnement, solutions de repli, idempotence et requêtes de couverture.Lire →9.5 · Intermédiaire · 24 minSLO et budgets d’erreurComment mesurer la fiabilité du point de vue de l’utilisateur avec des SLI, fixer des cibles de SLO, les transformer en budgets d’erreur et en politiques, déclencher des alertes sur le taux de consommation et garder les SLA prudemment plus souples que les objectifs internes.Lire →9.6 · Intermédiaire · 26 minObservabilitéComment voir à l’intérieur d’un système distribué en fonctionnement : journaux structurés, types de métriques et histogrammes, RED, USE et les signaux d’or, traçage distribué avec W3C Trace Context et OpenTelemetry, cardinalité et alertes fondées sur les symptômes.Lire →9.7 · Avancé · 25 minCapacité et testsComment planifier la capacité avant l’arrivée de la demande et vérifier qu’elle est bien là : prévisions, marge de capacité et délais d’approvisionnement, tests de charge, de stress, d’endurance, de pic et de point de rupture, charges ouvertes et fermées, omission coordonnée et budgets de performance.Lire →9.8 · Intermédiaire · 25 minChaos et incidentsComment trouver les faiblesses avant les utilisateurs et tirer les leçons des défaillances qui surviennent malgré tout : expériences de chaos et game days, coordination des incidents, niveaux de gravité et pages de statut, revues sans reproche, les limites du MTTR et des actions qui changent le système.Lire →

Test du chapitre

Vérifiez votre compréhension du chapitre 9

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 9 dans l’app

Lectures complémentaires