Presque tous les nouveaux employĂ©s de Yandex sont Ă©tonnĂ©s de l'ampleur des contraintes que subissent nos produits. Des milliers d'hĂŽtes avec des centaines de milliers de requĂȘtes par seconde. Et ce n'est lĂ qu'un des services. Dans ce cas, nous devons rĂ©pondre aux demandes en une fraction de seconde. MĂȘme un lĂ©ger changement dans le produit peut avoir un impact significatif sur les performances, il est donc important de tester et d'Ă©valuer l'impact de votre code sur le service.
Au sein de notre service des technologies publicitaires, les tests fonctionnent dans le cadre de la méthodologie d'intégration continue, dont nous discuterons plus en détail de l'organisation du 25 octobre lors de l'événement Yandex de l'intérieur , et aujourd'hui nous partagerons avec les lecteurs Habr l'expérience de l'automatisation de l'évaluation des métriques de produits importantes liées à la performance du service. Vous apprendrez à confier l'analyse à une machine, et non à les suivre sur des graphiques. C'est parti!

Il ne s'agit pas de tester le site. Il existe de nombreux outils en ligne pour cela. Aujourd'hui, nous allons parler d'un service backend interne trÚs chargé, qui fait partie d'un grand systÚme et prépare les informations pour un service externe. Dans notre cas, pour les pages de résultats de recherche et les sites partenaires. Si notre composant n'a pas le temps de répondre, les informations qu'il contient ne seront tout simplement pas transmises à l'utilisateur. Ainsi, l'entreprise perdra de l'argent. Par conséquent, il est trÚs important de répondre à temps.
Quelles mesures de serveur importantes peuvent ĂȘtre mises en Ă©vidence?
- Demande par seconde (RPS) . Le bonheur d'un utilisateur est bien sĂ»r important pour nous. Mais si ce n'est pas un, mais des milliers d'utilisateurs sont venus vers vous. Combien de requĂȘtes par seconde votre serveur peut-il supporter et ne pas tomber?
- Temps par demande . Le contenu du site doit ĂȘtre rendu le plus rapidement possible afin que l'utilisateur ne se lasse pas d'attendre et qu'il n'aille pas au magasin pour du pop-corn. Dans notre cas, il ne verra pas une partie importante des informations sur la page.
- Taille de l'ensemble résident (RSS) . Assurez-vous de surveiller la quantité de mémoire utilisée par votre programme. Si le service mange toute la mémoire, il n'est guÚre possible de parler de tolérance aux pannes.
- Erreurs HTTP .
Alors mettons-le dans l'ordre.
Demande par seconde
Notre développeur, qui s'occupe de tests de charge depuis longtemps, aime parler de la ressource critique du systÚme. Voyons voir ce que c'est.
Chaque systĂšme a ses propres caractĂ©ristiques de configuration qui dĂ©terminent le fonctionnement. Par exemple, la longueur de la file d'attente, le dĂ©lai de rĂ©ponse, le pool de threads, etc. Il peut donc arriver que la capacitĂ© de votre service repose sur l'une de ces ressources. Vous pouvez mener une expĂ©rience. Augmentez tour Ă tour chaque ressource. Une ressource, dont l'augmentation augmentera la capacitĂ© de votre service, sera critique pour vous. Dans un systĂšme bien configurĂ©, pour augmenter la capacitĂ©, vous devrez augmenter non pas une ressource, mais plusieurs. Mais cela peut encore ĂȘtre "ressenti". Ce sera formidable si vous pouvez configurer votre systĂšme de sorte que toutes les ressources fonctionnent Ă pleine puissance et que le service sâadapte dans les dĂ©lais qui lui sont impartis.
Pour estimer le nombre de requĂȘtes par seconde que votre serveur supportera, vous devez lui diriger un flux de requĂȘtes. Ătant donnĂ© que ce processus est intĂ©grĂ© au systĂšme CI, nous utilisons un «pistolet» trĂšs simple avec des fonctionnalitĂ©s limitĂ©es. Mais Ă partir d'un logiciel open source, Yandex.Tank est parfait pour cette tĂąche. Il a une documentation dĂ©taillĂ©e. Un cadeau Ă Tank est un service permettant de visualiser les rĂ©sultats.
Un petit dessus. Yandex.Tank a une fonctionnalité assez riche, non limitée à l'automatisation des demandes de décorticage. Il vous aidera également à collecter des métriques de votre service, à créer des graphiques et à fixer le module avec la logique dont vous avez besoin. En général, nous vous recommandons fortement de le connaßtre.
Vous devez maintenant envoyer des requĂȘtes au tank afin qu'il puisse tirer Ă notre service. Les requĂȘtes avec lesquelles vous shellerez le serveur peuvent ĂȘtre du mĂȘme type, créées et propagĂ©es artificiellement. Cependant, les mesures seront beaucoup plus prĂ©cises si vous pouvez collecter un vĂ©ritable pool de demandes d'utilisateurs pendant une certaine pĂ©riode de temps.
La capacitĂ© peut ĂȘtre mesurĂ©e de deux maniĂšres.
ModĂšle de charge ouverte (stress test)
CrĂ©ez des "utilisateurs", c'est-Ă -dire plusieurs threads qui enverront une demande Ă votre systĂšme. La charge que nous ne donnerons pas est constante, mais l'accumule ou la nourrit mĂȘme par vagues. Ensuite, cela nous rapprochera de la vie rĂ©elle. Nous augmentons le RPS et saisissons le point auquel le service bombardĂ© «franchit» le SLA. Ainsi, vous pouvez trouver les limites du systĂšme.
Pour calculer le nombre d'utilisateurs, vous pouvez utiliser la petite formule (vous pouvez la lire ici ). En omettant la théorie, la formule ressemble à ceci:
RPS = 1000 / T * travailleurs, oĂč
âą T - temps moyen de traitement des demandes (en millisecondes);
âą travailleurs - le nombre de fils;
âą 1000 / T requĂȘtes par seconde - cette valeur sera gĂ©nĂ©rĂ©e par un gĂ©nĂ©rateur Ă thread unique.
ModÚle de charge fermée (test de charge)
Nous prenons un nombre fixe d '«utilisateurs». Vous devez le configurer pour que la file d'attente d'entrĂ©e correspondant Ă la configuration de votre service soit toujours obstruĂ©e. Dans le mĂȘme temps, cela n'a aucun sens de faire un nombre de threads supĂ©rieur Ă la limite de file d'attente, car nous nous reposerons sur ce nombre, et les demandes restantes seront rejetĂ©es par le serveur avec une erreur 5xx. Nous regardons combien de requĂȘtes par seconde le design pourra Ă©mettre. Un tel schĂ©ma dans le cas gĂ©nĂ©ral n'est pas similaire au flux rĂ©el de requĂȘtes, mais il aidera Ă montrer le comportement du systĂšme Ă la charge maximale et Ă Ă©valuer son dĂ©bit actuel.
Pour la grande majoritĂ© des systĂšmes (oĂč la ressource critique n'est pas liĂ©e au traitement des connexions), le rĂ©sultat sera le mĂȘme. Dans le mĂȘme temps, le modĂšle fermĂ© a moins de bruit, car le systĂšme est dans la zone de charge qui nous intĂ©resse tout le temps du test.
Lors du test de notre service, nous utilisons un modÚle fermé. AprÚs le tir, le pistolet nous indique le nombre de demandes par seconde que notre service a pu émettre. Yandex.Tank cet indicateur est également facile à dire.
Temps par demande
Si nous revenons au paragraphe prĂ©cĂ©dent, il devient Ă©vident qu'avec un tel schĂ©ma, cela n'a aucun sens d'Ă©valuer le temps de rĂ©ponse Ă une requĂȘte. Plus le systĂšme est chargĂ©, plus il se dĂ©grade et plus il rĂ©pond. Par consĂ©quent, pour tester le temps de rĂ©ponse, l'approche doit ĂȘtre diffĂ©rente.
Pour obtenir le temps de rĂ©ponse moyen, nous utiliserons le mĂȘme Yandex.Tank. Ce n'est que maintenant que nous fixerons le RPS correspondant Ă l'indicateur moyen de votre systĂšme en production. AprĂšs le bombardement, nous obtenons des temps de rĂ©ponse pour chaque demande. Sur la base des donnĂ©es collectĂ©es, des centiles de temps de rĂ©ponse peuvent ĂȘtre calculĂ©s.
Ensuite, vous devez comprendre quel centile nous considérons important. Par exemple, nous misons sur la production. Nous pouvons laisser 1% des demandes d'erreurs, des non-réponses, des demandes de débogage qui fonctionnent longtemps, des problÚmes avec le réseau, etc. Par conséquent, nous considérons comme important le temps de réponse, qui prend en charge 99% des demandes.
Taille de l'ensemble résident
Notre serveur fonctionne directement avec les fichiers via mmap . En mesurant l'index RSS, nous voulons savoir combien de mémoire le programme a pris au systÚme d'exploitation pendant le fonctionnement.
Sous Linux, le fichier / proc / PID / smaps est écrit - il s'agit d'une extension basée sur une carte qui montre la consommation de mémoire pour chacun des mappages de processus. Si votre processus utilise tmpfs, la mémoire anonyme et non anonyme sera mise en smaps. La mémoire non anonyme comprend, par exemple, les fichiers chargés en mémoire. Voici un exemple d'entrée dans smaps. Un fichier spécifique est spécifié et son paramÚtre Anonymous = 0kB.
7fea65a60000-7fea65a61000 r--s 00000000 09:03 79169191 /place/home/.../some.yabs Size: 4 kB Rss: 4 kB Pss: 4 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 4 kB Private_Dirty: 0 kB Referenced: 4 kB Anonymous: 0 kB AnonHugePages: 0 kB Swap: 0 kB KernelPageSize: 4 kB MMUPageSize: 4 kB Locked: 0 kB VmFlags: rd mr me ms
Et ceci est un exemple d'allocation de mĂ©moire anonyme. Lorsqu'un processus (le mĂȘme mmap) demande au systĂšme d'exploitation d'allouer une certaine taille de mĂ©moire, une adresse lui est allouĂ©e. Alors que le processus ne prend que de la mĂ©moire virtuelle. Ă ce stade, nous ne savons pas encore quel morceau de mĂ©moire physique sera allouĂ©. Nous voyons un record sans nom. Ceci est un exemple d'allocation de mĂ©moire anonyme. Le systĂšme a Ă©tĂ© demandĂ© la taille de 24572 kB, mais ils ne l'ont pas utilisĂ© et en fait seulement RSS = 4 kB a Ă©tĂ© pris.
7fea67264000-7fea68a63000 rw-p 00000000 00:00 0 Size: 24572 kB Rss: 4 kB Pss: 4 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 4 kB Referenced: 4 kB Anonymous: 4 kB AnonHugePages: 0 kB Swap: 0 kB KernelPageSize: 4 kB MMUPageSize: 4 kB Locked: 0 kB VmFlags: rd wr mr mw me ac
Ătant donnĂ© que la mĂ©moire non anonyme allouĂ©e n'ira nulle part aprĂšs l'arrĂȘt du processus, le fichier ne sera pas supprimĂ©, nous ne sommes pas intĂ©ressĂ©s par ce RSS.
Avant de commencer à tirer sur le serveur, nous résumons le flux RSS de / proc / PID / smaps, alloué à la mémoire anonyme, et nous nous en souvenons. Nous procédons au décorticage, similaire au temps de test par demande. AprÚs avoir terminé, pensez à nouveau à RSS. La différence entre l'état initial et l'état final sera la quantité de mémoire utilisée par votre processus pendant le fonctionnement.
Erreurs HTTP
N'oubliez pas de suivre les codes de rĂ©ponse que le service renvoie lors des tests. Si quelque chose s'est mal passĂ© lors de la configuration d'un test ou d'un environnement et que le serveur a renvoyĂ© des erreurs 5xx et 4xx pour toutes vos demandes, il n'y avait pas grand intĂ©rĂȘt Ă un tel test. Nous surveillons la proportion de mauvaises rĂ©ponses. S'il y a beaucoup d'erreurs, le test est considĂ©rĂ© comme invalide.
Un peu sur la précision des mesures
Et maintenant, la chose la plus importante. Revenons aux paragraphes prĂ©cĂ©dents. Il se trouve que les valeurs absolues des mĂ©triques calculĂ©es par nous ne sont pas si importantes pour nous. Non, bien sĂ»r, vous pouvez atteindre la stabilitĂ© des indicateurs, en tenant compte de tous les facteurs, erreurs et fluctuations. En parallĂšle, Ă©crivez un travail scientifique sur ce sujet (au fait, si quelqu'un en recherche un, cela pourrait ĂȘtre une bonne option). Mais ce n'est pas cela qui nous intĂ©resse.
Il est important pour nous d'influencer la validation spĂ©cifique sur le code par rapport Ă l'Ă©tat prĂ©cĂ©dent du systĂšme. C'est-Ă -dire que la diffĂ©rence entre les mĂ©triques de validation en validation est importante. Et ici, il est nĂ©cessaire de mettre en place un processus qui comparera cette diffĂ©rence et garantira en mĂȘme temps la stabilitĂ© de la valeur absolue dans cet intervalle.
L'environnement, les demandes, les donnĂ©es, l'Ă©tat du service - tous les facteurs Ă notre disposition doivent ĂȘtre fixes. C'est ce systĂšme qui fonctionne pour nous dans le cadre de l'intĂ©gration continue, nous fournissant des informations sur toutes sortes de changements survenus au sein de chaque commit. MalgrĂ© cela, il ne sera pas possible de tout rĂ©parer, il y aura du bruit. On peut rĂ©duire le bruit, Ă©videmment, en augmentant l'Ă©chantillon, c'est-Ă -dire faire plusieurs itĂ©rations de la prise de vue. De plus, aprĂšs avoir tournĂ©, disons, 15 itĂ©rations, nous pouvons calculer la mĂ©diane de l'Ă©chantillon rĂ©sultant. De plus, il est nĂ©cessaire de trouver un Ă©quilibre entre le bruit et la durĂ©e de la prise de vue. Par exemple, nous avons retenu une erreur de 1%. Si vous souhaitez choisir une mĂ©thode statistique plus complexe et prĂ©cise en fonction de vos besoins, nous vous recommandons un livre qui rĂ©pertorie les options avec une description de quand et laquelle est utilisĂ©e.
Que peut-on faire d'autre avec le bruit?
Notez que l'environnement dans lequel vous effectuez des tests joue un rĂŽle important dans ces tests. Le banc de test doit ĂȘtre fiable, il ne doit pas exĂ©cuter d'autres programmes, car ils peuvent conduire Ă la dĂ©gradation de votre service. De plus, les rĂ©sultats peuvent et dĂ©pendront du profil de charge, de l'environnement, de la base de donnĂ©es et de divers «orages magnĂ©tiques».
Dans le cadre d'un test de validation unique, nous effectuons plusieurs itĂ©rations sur diffĂ©rents hĂŽtes. PremiĂšrement, si vous utilisez le cloud, tout peut y arriver. MĂȘme si le cloud est spĂ©cialisĂ©, comme le nĂŽtre, les processus de service y fonctionnent toujours. Par consĂ©quent, vous ne pouvez pas compter sur le rĂ©sultat d'un hĂŽte. Et si vous avez un hĂŽte de fer, oĂč il n'y a pas, comme dans le cloud, de mĂ©canisme standard pour Ă©lever l'environnement, vous pouvez mĂȘme le casser une fois et le laisser ainsi. Et il vous mentira toujours. Par consĂ©quent, nous effectuons nos tests dans le cloud.
Certes, une autre question en découle. Si vos mesures sont effectuées à chaque fois sur des hÎtes différents, les résultats peuvent faire un peu de bruit et à cause de cela. Ensuite, vous pouvez normaliser les lectures sur l'hÎte. Autrement dit, selon les données historiques, collecter le «coefficient hÎte» et en tenir compte lors de l'analyse des résultats.
L'analyse des données historiques montre que le matériel est différent. Le mot «matériel» inclut ici la version du noyau et les conséquences de la disponibilité (apparemment, les objets du noyau non mobiles en mémoire).
Ainsi, à chaque "hÎte" (au redémarrage, l'hÎte "meurt" et un "nouveau" apparaßt) nous associons l'amendement par lequel nous multiplions le RPS avant agrégation.
Nous considĂ©rons et mettons Ă jour les amendements d'une maniĂšre extrĂȘmement maladroite, rappelant Ă©trangement une option de formation de renforcement.
Pour un vecteur donné de corrections postérieures, nous considérons la fonction objectif:
- dans chaque test, nous considérons l'écart type des résultats RPS «corrigés» obtenus
- prendre la moyenne d'eux avec des poids égaux ,
- nous avons tau = 1 semaine.
Ensuite, nous fixons une correction (pour l'hĂŽte avec la plus grande somme de ces poids) Ă 1,0 et recherchons les valeurs de toutes les autres corrections qui donnent un minimum de la fonction objectif.
Afin de valider les résultats sur les données historiques, nous considérons les corrections sur les anciennes données, nous considérons le résultat corrigé sur le frais, comparons avec le non corrigé.
Une autre option pour ajuster les rĂ©sultats et rĂ©duire le bruit est la normalisation des «synthĂ©tiques». Avant de dĂ©marrer le service Ă tester, exĂ©cutez un «programme synthĂ©tique» sur l'hĂŽte, Ă partir duquel vous pouvez Ă©valuer l'Ă©tat de l'hĂŽte et calculer le facteur de correction. Mais dans notre cas, nous utilisons des corrections basĂ©es sur l'hĂŽte, et cette idĂ©e est restĂ©e une idĂ©e. Peut-ĂȘtre que l'un d'entre vous l'aimera.
MalgrĂ© l'automatisation et tous ses avantages, n'oubliez pas la dynamique de vos indicateurs. Il est important de s'assurer que le service ne se dĂ©grade pas avec le temps. Vous ne remarquerez peut-ĂȘtre pas de petits rabattements, ils peuvent s'accumuler et, sur une longue pĂ©riode, vos indicateurs peuvent s'affaisser. Voici un exemple de nos graphiques que nous examinons Ă RPS. Il montre la valeur relative de chaque validation vĂ©rifiĂ©e, son numĂ©ro et la possibilitĂ© de voir d'oĂč la version a Ă©tĂ© allouĂ©e.


Si vous lisez l'article, il sera certainement intéressant pour vous de voir un rapport sur Yandex.Tank et une analyse des résultats des tests de charge.
Nous vous rappelons également que plus en détail sur l'organisation de l'intégration continue nous parlerons du 25 octobre lors de l'événement Yandex de l'intérieur . Venez visiter!