Les pics de latence peuvent être une réalité frustrante pour de nombreuses organisations, en particulier en ce qui concerne les centiles de queue. Il n’est pas rare de voir des pics de latence inexpliqués, en particulier lorsqu’il n’y a pas de concentration délibérée sur la prévisibilité.
Considérez un scénario dans lequel un service Web doit restituer une page Web personnalisée. Pour offrir une bonne expérience utilisateur, il est nécessaire de garantir une faible latence pour 90 % à 95 % des requêtes. Cependant, le contenu de la page peut nécessiter des dizaines voire des centaines de sous-requêtes provenant de divers composants, chacune avec sa propre variance et son caractère aléatoire. Bien que chaque composant puisse avoir une faible latence dans 99 % des cas, cela peut ne pas être suffisant pour garantir une latence cohérente pour l’utilisateur final. Cela souligne l’importance d’avoir les bons objectifs de couche de service (SLO) pour chaque composant afin de garantir les performances globales du système.
Pour réduire la variance, il faut comprendre les statistiques et les probabilités, ce qui peut être difficile même pour les statisticiens formés. Cependant, des modèles mentaux simples et des heuristiques peuvent aider à développer l’intuition et à mieux comprendre la mécanique du système. Ceci peut être réalisé en exécutant des simulations mathématiques et en jouant avec des paramètres pour voir comment chaque dimension affecte le résultat final.
Qu’est-ce que le hasard exactement ? Philosophiquement, il n’y a pas de définition stricte pour cela. C’est une question de perspective, et à la fois « tout est aléatoire » et « rien ne l’est » peuvent être défendables. Concrètement, le hasard est défini comme un résultat qui ne peut pas être prédit à l’avance. Cependant, s’il existe un modèle ou une distribution à long terme des résultats, il peut être considéré comme aléatoire à des fins pratiques.
Dans cet article de blog, nous explorerons le concept de centiles de queue et comment évaluer et gérer le caractère aléatoire de ceux-ci. Des ateliers de programmation interactifs seront fournis dans certaines sections pour vous aider à approfondir votre compréhension des concepts.
Modélisation mathématique
La première étape pour réduire la latence de queue consiste à créer un modèle qui représente avec précision les caractéristiques de votre système. Gardez le modèle aussi simple que possible tout en vous assurant qu’il capture toujours les éléments essentiels de votre système. La simplicité facilite la compréhension et réduit le risque de mauvaise interprétation. Mais attention à ne pas trop simplifier, car cela pourrait conduire à une représentation inadéquate du système. L’objectif est de trouver un équilibre entre simplicité et précision.
Travailler avec des modèles aide à entraîner votre cerveau à attribuer un poids approprié à diverses entrées. Cet exercice aide à améliorer votre intuition professionnelle et vos compétences en ingénierie et vous fait gagner du temps en éliminant rapidement les hypothèses incorrectes et en évitant les solutions coûteuses et sans issue.
Nous pouvons déconstruire la latence de fonctionnement en deux composants principaux :
latency = fixed_price + random_delay
fixed_price
— le coût fixe représente le coût minimum d’exécution du travail, comme les cycles CPU pour les calculs ou le temps de déplacement des données, qui ne peut être réduit.random_delay
— le surplus imprévisible causé par divers facteurs tels que les conflits de threads, la perte de paquets ou la congestion du réseau.
Disposer d’un ensemble de micro-repères qui couvrent tous les principaux composants du système peut aider à déterminer le coût fixe. En collectant suffisamment d’échantillons, le coût fixe peut être calculé comme la limite inférieure, tandis que le retard aléatoire peut être dérivé de la variance observée. Cela peut être mesuré par l’écart type et les centiles de latence (voir également Mesure des performances du service réseau).
Compréhension intuitive des centiles
Les métriques centiles telles que p50, p90, p99, p99.9, etc., sont couramment utilisées pour mesurer la latence des requêtes. En termes simples, les centiles indiquent le coût de base pour atteindre de « mauvaises » conditions. Par exemple, p90 représente les pires 10 % des causes et p99 représente les pires 1 % des causes.
Imaginez un service qui a un cache L1 avec un taux de réussite de 80 %. Cela signifie que dans 20 % des cas, les données doivent être lues à partir de la base de données. La latence p80 représenterait le coût minimum d’un retour à la base de données. Si la base de données possède également un cache L2 avec un taux de réussite de 50 %, les centiles de latence ressembleraient à ceci :

p80
— latence lorsque leL1
le cache contient des données.p90
– quandL1
n’a pas de données maisL2
a des données.p90+
— lorsque la BD doit lire des données sur le disque.
Des centiles plus élevés indiquent une moins bonne chance et peuvent résulter de diverses causes telles que la gestion des pannes, la perte de paquets, la saturation des ressources, les tentatives, les retours en arrière, etc.
Budget aléatoire
Les centiles peuvent également être considérés en termes de budget aléatoire. Par exemple, si nous voulons garantir un p95 à un certain niveau, nous avons un budget d’aléatoire de 5 % qui peut être utilisé pour les caches manqués, les replis, etc. Le défi consiste alors à répartir ce budget entre les dépendances en amont.
Notez que la probabilité n’est pas additive, donc la division arithmétique ne peut pas être utilisée pour les calculs. La division dépend de la façon dont les dépendances en amont sont appelées, que ce soit en parallèle ou en série. La méthode de calcul varierait selon les modèles d’appel.
Centiles d’opérations multiples
Commençons par établir notre terminologie :
- Service — un composant qui génère le résultat final.
- Dépendance — un composant en amont qui est appelé par le service pour obtenir des données.
- Opération – une unité de travail effectuée par Service.
- Sous-demande — une unité de travail effectuée par Dépendance. Nous supposons que toutes les sous-requêtes d’une opération sont indépendantes.
Quelle est la relation entre la latence de l’opération et la latence de la sous-requête ? Examinons deux cas :
- Plusieurs sous-requêtes sont exécutées en parallèle.
- Plusieurs sous-requêtes sont exécutées séquentiellement.
Sous-demandes parallèles et centiles de fin
Supposons qu’un service doive effectuer plusieurs sous-requêtes à Dependency en parallèle :

En supposant que nous nous intéressons au p99 de la latence de fonctionnement, s’agirait-il uniquement de la sous-requête qui relève de la catégorie p99 ? En fait non. Examinons pourquoi. Le cas le plus simple est lorsqu’il y a deux requêtes.
Comme vous vous en souvenez ci-dessus, p99 – signifie le pire 1%. Alors, quelle est la probabilité que les deux demandes tombent avec bonheur dans les 99 % de bons cas ?

La probabilité que deux événements indépendants se produisent ensemble est calculée en multipliant leurs probabilités individuelles. Par exemple, si chaque événement a une probabilité de 0,99 (ou 99 %), la probabilité combinée que les deux événements se produisent est de 0,99 * 0,99 = 0,9801.
Il est important de convertir les pourcentages en valeurs comprises entre 0 et 1 lorsque vous travaillez avec des probabilités. Cela nous permet d’effectuer des opérations mathématiques avec eux.
Par conséquent, la probabilité de ne pas atteindre le 99e centile pour une sous-demande est de 0,9801, soit 98,01 %. Cela signifie que les pires 1 % des sous-requêtes se produiront dans 2 % des opérations de service.
Faisons le même calcul dans le cas de 10 sous-requêtes :

Désormais, les pires 1 % des sous-demandes affecteront 9,5 % de nos opérations. Cela met en évidence le problème de s’appuyer uniquement sur le p99 d’une dépendance. La question est de savoir quel est le centile approprié à examiner pour la latence des sous-requêtes ? Cela implique de trouver l’inverse – si nous voulons que l’aire du carré vert soit de 0,99, alors sa longueur de côté correspond au p99,5 de la latence de dépendance. Dans le cas de 10 sous-requêtes, le centile correspondant est p99,9 de latence de dépendance.
Voici à quoi peut ressembler la fonction du point centile (PPF) dans le cas de 10 sous-requêtes :
Vous pouvez jouer avec une démonstration empirique de cette formule pour avoir une meilleure idée en essayant différents paramètres à l’aide de ce Codelab.
Exécution séquentielle de la demande de frottement
Changeons maintenant notre scénario. Supposons que nous ayons besoin du résultat d’une sous-requête pour passer à la suivante. Dans ce cas, les sous-requêtes doivent être exécutées dans l’ordre :
Pour faire simple, supposons que tous les services ont un modèle de latence similaire qui est généralement cohérent mais qui montre une certaine déviation dans ses valeurs aberrantes.
En règle générale, une distribution log-normale est efficace pour modéliser la latence du réseau.
Un processus log-normal est la réalisation statistique du produit multiplicatif de nombreuses variables aléatoires indépendantes, dont chacune est positive.
Exemples de valeurs distribuées log-normales dans le monde réel (en plus de la latence d’une opération) :
- La longueur des commentaires publiés dans les forums de discussion sur Internet suit une distribution log-normale.
- Le temps d’attente des utilisateurs sur les articles en ligne (blagues, actualités, etc.) suit une distribution log-normale.
- La durée des parties d’échecs a tendance à suivre une distribution log-normale.
- Les résolutions de Rubik’s Cube, à la fois générales ou par personne, semblent suivre une distribution log-normale.
Cette approche peut également être utilisée pour Loi de Pareto, qui peut être mieux adapté aux systèmes avec de fortes variances de queue. Vous pouvez expérimenter cela en basculant la distribution sur Pareto dans les Codelabs et en observant l’impact sur les résultats. Les mêmes calculs mathématiques peuvent toujours être utilisés même si la variance affecte principalement la queue.
Par exemple, si le PPF ressemble à ceci :
Pour obtenir la variance, nous pouvons soustraire le minimum (c’est-à-dire fixed_price
) valeur de la latence. Ensuite, nous pouvons calculer la latence de fonctionnement en ajoutant le fixed_price
et variance
:
latence(n) = n * prix_fixe + variance(n)
L’approche heuristique peut ne pas être entièrement précise dans certains cas, mais elle est efficace pour un petit nombre de sous-requêtes, jusqu’à plusieurs dizaines. Par exemple, si deux requêtes sont exécutées en parallèle, le centile de la sous-requête serait p99,5, alors qu’il serait p99,53 dans le cas d’une exécution séquentielle :
Pourquoi cette heuristique fonctionne-t-elle ? Étant donné que les valeurs aberrantes ont un impact significatif sur la queue et que la probabilité que deux valeurs aberrantes se produisent ensemble est très faible, nous pouvons l’ignorer.
Essayons le modèle avec dix sous-requêtes :
Le centile réel…