Guides

Guide d'architecture logicielle

Budgets de latence des systèmes distribués : concevoir, mesurer, appliquer

Un budget de latence fait de la performance une contrainte architecturale : chaque périphérie, service, dépendance, nouvelle tentative et file d'attente reçoit une part explicite du temps d'attente acceptable pour l'utilisateur.

La latence est une propriété d'un parcours de bout en bout, et non d'un unique service rapide. Un paiement qui commence dans un navigateur, traverse une périphérie, appelle trois services, attend une base de données et émet un événement peut manquer son objectif côté utilisateur même lorsque chaque équipe affiche un temps de réponse moyen respectable.

Un budget de latence transforme ce problème vague en outil de conception. Partez d'un résultat utilisateur, fixez un objectif fondé sur un percentile, allouez du temps aux étapes réellement sur le chemin critique et conservez une marge pour les variations et la gestion des défaillances. Le résultat n'est pas la promesse que chaque requête sera rapide. C'est un cadre de décision partagé par l'ingénierie, les opérations et les fournisseurs.

Budgétez la queue de distribution, pas la moyenne

Les moyennes masquent les files d'attente, les chemins à froid, les pertes de paquets et les blocages de dépendances. Définissez les objectifs de parcours avec des percentiles tels que p95 ou p99, puis examinez les distributions par région, route, état du cache et dépendance plutôt que de considérer un unique chiffre mondial comme une preuve.

Commencez par le parcours utilisateur

Définissez la transaction avant de la mesurer. « Latence de l'API » est trop vaste ; « un client connecté reçoit les résultats de recherche de produits » identifie un chemin qui peut être instrumenté et protégé. Consignez le lieu d'origine, la catégorie de réseau, la méthode de requête, la taille de charge utile, l'état d'authentification, la possibilité de mise en cache, les appels en aval et la réponse qui achève le parcours.

Utilisez des objectifs distincts pour des tâches matériellement différentes. Une page de catalogue mise en cache, une requête de recherche authentifiée et une autorisation de paiement ont des exigences de correction différentes et ne peuvent pas partager une même cible de latence de façon sûre. Incluez les conditions de disponibilité et de correction avec le temps : un prix obsolète obtenu rapidement ou une réponse de paiement partielle obtenue rapidement ne constituent pas une transaction réussie.

Exemple de budget pour un chemin de lecture

Pour une cible p95 de 600 ms entre un client régional et une réponse API rendue, une équipe pourrait allouer :

ÉtapeBudgetQuestion architecturale
Client, DNS, TLS et transit réseau180 msLa réutilisation de connexion, HTTP/2 ou HTTP/3 et un placement edge régional peuvent-ils réduire le temps de préparation évitable ?
Politique edge et consultation du cache35 msLa requête peut-elle être mise en cache, regroupée ou rejetée avant l'origine sans risque ?
Passerelle d'origine et travail du service160 msQuels appels sont sur le chemin critique et lesquels peuvent s'exécuter de manière asynchrone ?
Base de données et dépendances distantes120 msLes délais d'expiration sont-ils bornés, les pools dimensionnés et les requêtes indexées pour la concurrence attendue ?
Sérialisation, transit de la réponse et marge105 msLa taille de la réponse correspond-elle à la réalité du réseau et reste-t-il une marge pour la variation normale ?

Ce sont des allocations de planification, et non des mesures à additionner aveuglément. Le travail parallèle consomme le temps écoulé de sa branche la plus lente, tandis que les appels séquentiels s'additionnent. Rendez cette distinction explicite dans un diagramme de dépendances ; sinon, un budget peut faire paraître anodin un fan-out séquentiel.

Déduisez les budgets du chemin critique

Dessinez le chemin de requête depuis le client, via DNS, CDN ou edge, passerelle, services, magasins de données et tiers. Marquez chaque arête comme séquentielle, parallèle, facultative, mise en cache ou asynchrone. Attribuez ensuite une échéance à la requête et des échéances plus courtes aux travaux qui doivent se terminer avant celle-ci.

Une hiérarchie efficace de délais d'expiration laisse du temps à l'appelant pour réagir. Si la passerelle dispose de 700 ms, un service ne devrait pas lancer un appel de base de données de 700 ms après avoir passé 300 ms sur une requête en amont. Propagez une échéance, et pas seulement des délais d'expiration fixes indépendants. Les services doivent refuser un travail qui ne peut plus se terminer utilement, libérer les ressources et signaler une raison d'expiration qui rende visible l'étape ayant épuisé le budget.

Les nouvelles tentatives nécessitent leur propre budget. Une nouvelle tentative ne peut améliorer une défaillance transitoire que s'il reste assez de temps, que l'opération peut être répétée sans risque et qu'elle n'amplifiera pas une dépendance déjà sous charge. Utilisez un nombre de tentatives borné, un backoff avec gigue, des limites de tentatives par requête et des clés d'idempotence pour les opérations ayant des effets métier. Ne répétez pas automatiquement une requête expirée lorsque l'opération d'origine peut encore se terminer.

Considérez la mise en file d'attente comme un signal de latence

Lorsque l'utilisation approche la capacité, le temps d'attente augmente souvent plus vite que le débit de requêtes. Le CPU peut sembler acceptable tandis qu'un pool de connexions fini, une partition de base de données unique, un pool de threads ou une limite de concurrence en amont crée une file d'attente. Mesurez la profondeur de file, la durée d'attente, la concurrence active, la saturation et le taux de rejet avec la latence des requêtes.

Gardez volontairement le travail synchrone réduit. Déplacez vers une file durable le travail non essentiel, comme les notifications, le traitement d'images, l'enrichissement analytique et certains rapprochements, lorsque le flux métier le permet. Une file protège l'appelant d'un worker lent, mais n'efface pas la latence : l'âge de la file fait partie de l'objectif de réalisation. Définissez des cibles distinctes pour le délai d'acceptation et le délai de réalisation de bout en bout.

Appliquez un contrôle d'admission avant qu'une dépendance soit saturée. Une file bornée, une limite de concurrence, une réponse de délestage ou une réponse dégradée peuvent préserver un travail utile pour davantage d'utilisateurs qu'une attente illimitée. Les recommandations Google SRE sur la surcharge soulignent cette distinction : accepter un travail qui ne peut pas être achevé consomme des ressources et peut ralentir la récupération.

Utilisez le cache et les contrôles edge sans compromettre la correction

La périphérie est souvent l'endroit où répondre à une requête ou la rejeter coûte le moins de latence, mais la configuration du cache fait partie de la correction applicative. Mettez en cache les réponses publiques dont la représentation est stable avec une politique Cache-Control explicite. Ne mettez pas en cache des réponses authentifiées ou personnalisées dans un cache partagé, à moins que la clé de cache et le modèle d'autorisation ne rendent l'isolation démontrable.

Pour le contenu pouvant être mis en cache, définissez la clé de cache, la durée de fraîcheur, le comportement de validation, le chemin d'invalidation et la politique de service de contenu obsolète. stale-while-revalidate peut réduire la latence d'origine pour les lectures tolérantes ; stale-if-error peut préserver une réponse précédemment valide lors d'une défaillance de l'origine. Aucun des deux ne convient à un inventaire évoluant rapidement, à des décisions d'autorisation ou à un état financier sans une décision produit explicite.

Protégez la capacité de l'origine lors des échecs de cache. Activez le regroupement de requêtes ou un comportement single-flight lorsqu'il est disponible afin que de nombreux échecs simultanés pour le même objet ne deviennent pas un troupeau d'éléphants. Utilisez un origin shield ou un niveau régional contrôlé pour consolider le trafic des échecs de cache. Définissez les limites de connexions, de débit de requêtes et de concurrence de l'origine indépendamment de la capacité edge publique, et exigez un accès edge-à-origine authentifié afin que les clients ne puissent pas contourner ces contrôles.

Instrumentez le budget au-delà des frontières

Un identifiant de requête unique est utile ; les traces distribuées le sont davantage lorsqu'elles préservent les relations parent-enfant, le timing, le statut, les nouvelles tentatives et l'état du cache. Adoptez les conventions sémantiques OpenTelemetry lorsque cela est pratique pour HTTP, RPC, les bases de données, la messagerie et les ressources cloud. Propagez le contexte de trace standard à travers les passerelles, services, workers et messages asynchrones.

Au minimum, ajoutez ces dimensions à la télémétrie de latence :

  • Nom de route et d'opération, et non des URL brutes non bornées ou des identifiants utilisateur.
  • Région, emplacement edge lorsqu'il est disponible, catégorie de réseau client et version de déploiement.
  • État du cache, état de l'origin shield, taille de réponse et version de protocole.
  • Nom de la dépendance, numéro de tentative, source du délai d'expiration, état du circuit et temps d'attente en file.
  • Classe de résultat : succès, rejet attendu, échéance dépassée, annulation ou défaillance de dépendance.

Utilisez les métriques pour les alertes et la détection de tendances, les traces pour le diagnostic du chemin critique et les journaux échantillonnés comme éléments de preuve. Contrôlez la cardinalité et masquez les secrets, jetons, charges utiles et données personnelles. Une conception d'observabilité qui surcharge le stockage ou divulgue le contenu des requêtes n'améliore pas la fiabilité.

Rendez explicites les compromis de fiabilité

Une latence plus faible et une cohérence plus forte peuvent entrer en conflit lorsque les données couvrent plusieurs régions. Un modèle de lecture répliqué mondialement peut améliorer les lectures proches tout en renvoyant des données légèrement plus anciennes. Une écriture synchrone interrégionale peut renforcer les garanties de durabilité tout en ajoutant un délai réseau et en couplant la disponibilité à davantage d'emplacements. Décidez par opération si la priorité est la fraîcheur, la cohérence, la faible latence ou la réalisation en cas de partition, et documentez le comportement de repli.

De même, une distribution multi-fournisseurs peut réduire la dépendance à un réseau, mais elle ajoute de la complexité de cache, routage, certificats, journalisation et gestion d'incident. Ne routez que lorsque les signaux de santé sont pertinents, incluez une hystérésis pour empêcher les basculements répétés et répétez une défaillance partielle de fournisseur. Une architecture neutre vis-à-vis des fournisseurs signifie définir le comportement requis, la télémétrie, les interfaces et le chemin de sortie avant de choisir une implémentation spécifique.

Exploitez le budget

Révisez un budget de latence lorsqu'un parcours utilisateur, une dépendance, la forme du trafic ou la topologie de déploiement change. Pour chaque objectif, maintenez un tableau de bord montrant p50, p95, p99, le taux d'erreur, la saturation, le taux de hit du cache et les plus grands contributeurs à la durée des traces. Comparez les sondes synthétiques à la télémétrie d'utilisateurs réels ; une sonde saine depuis une région cloud ne représente pas tous les réseaux clients.

Lors d'un incident, déterminez d'abord si la régression se situe au niveau client/réseau, edge, origine, service, magasin de données ou tiers. Évitez d'augmenter les délais d'expiration comme première réponse. Des attentes plus longues peuvent augmenter la concurrence et aggraver une file. Préférez une atténuation ciblée : servir une représentation mise en cache sûre, délester une fonctionnalité non critique, réduire le fan-out, suspendre une charge batch ou déplacer le trafic après avoir validé la capacité et le comportement des données.

Liste de contrôle du budget de latence

Avant d'approuver un chemin critique, confirmez qu'il dispose d'un objectif p95 ou p99 orienté utilisateur ; que les dépendances séquentielles et parallèles sont cartographiées ; que les échéances sont propagées ; que les nouvelles tentatives sont bornées et idempotentes lorsque nécessaire ; que le comportement du cache est sûr pour les données ; que l'origine a une capacité protégée ; que l'âge de la file est surveillé ; et que les traces peuvent relier les timings edge, applicatifs et des dépendances.

Références faisant autorité

Transformez les objectifs de performance en architecture déployable

Échangez avec les experts Optimi sur les budgets de latence, la mise en cache edge, la protection de l'origine et l'observabilité de la diffusion.

Discuter de l'architecture de performance