Tester une requête HTTP sous charge
Un nœud Requête HTTP peut envoyer sa requête de nombreuses fois, selon un profil de requêtes par seconde, beaucoup en même temps — et mesurer ce qui revient : percentiles de latence, erreurs, débit atteint. Des seuils décident si l’étape réussit, et le bouton Comparer place les chiffres à côté de ceux d’une exécution précédente.
Une charge est un réglage du nœud, pas un nœud à part : le reste de l’expérience — émulateurs, relais de dégradation, autres branches — s’exécute autour d’elle comme d’habitude.
Mettre une requête sous charge
- Sélectionnez un nœud Requête HTTP et remplissez sa requête.
- Dans ses propriétés, activez envoyer sous charge.
- Choisissez un Profil et ses valeurs. Le graphique en dessous, Débit dans le temps, trace le débit et indique à combien de requêtes il correspond, et en combien de secondes.
- Réglez le champ En parallèle — combien de requêtes peuvent être en cours en même temps.
- Ajoutez ou modifiez des Seuils.
- Exécutez l’expérience.
Une nouvelle charge est une Rampe de 0 à 100 requêtes par seconde sur 30 000 ms, 32 en parallèle, avec deux seuils : p95 < 500 ms et Erreurs < 1 %.
La charge remplace la répétition et le réessai. L’activer les désactive, et un nœud qui a une charge et l’un d’eux est refusé (node.load_alone) : une requête échouée est comptée, pas retentée. Seule une requête HTTP peut s’exécuter sous charge (node.load_unsupported).
La requête est lue une seule fois. Ses modèles sont résolus au démarrage de l’étape : chaque requête de la charge est donc la même — {{counter}} et {{uuid}} prennent une seule valeur pour toutes. Voir modèles.
Un seul client pour toute la charge. Les requêtes partagent la réserve de cookies de l’exécution quand l’option Conserver les cookies entre les requêtes est cochée, et une seule mémoire Digest : un seul challenge leur répond à toutes. Chaque requête a le délai d’attente propre au nœud.
L’Inspecteur reçoit un échantillon : au plus un échange toutes les 100 ms, pour qu’une charge n’inonde pas l’onglet Inspecteur.
Profils
| Profil | Réglages | Le débit dans le temps |
|---|---|---|
| Constant | Débit, req/s, Durée, ms | le débit d’un bout à l’autre |
| Rampe | De, req/s, À, req/s, Durée, ms | en ligne droite d’un débit à l’autre |
| Paliers | De, req/s, Palier, req/s, Chacun, ms, Paliers | le premier débit, puis un palier de plus à chaque niveau, chaque niveau pendant la même durée |
| Pic | Base, req/s, Pointe, req/s, Pic à, ms, Pic pendant, ms, Durée, ms | le débit de base, la pointe pendant un moment à partir d’un instant donné, puis de nouveau le débit de base |
| Aléatoire | Débit, req/s, Durée, ms | des arrivées au hasard, le débit en moyenne |
Changer de forme conserve ce qui peut l’être : la durée et le débit le plus élevé atteint.
Limites
| Réglage | Plage |
|---|---|
| Débit, req/s de Constant et Aléatoire, Pointe, req/s | 0,1–100 000 requêtes/s |
| De, req/s, À, req/s, Base, req/s | 0–100 000 requêtes/s |
| Chaque niveau de Paliers, le dernier compris | 0–100 000 requêtes/s ; le palier peut être négatif |
| Durée, ms, Chacun, ms | 100–300 000 ms |
| Paliers | 1–100, et tous les niveaux ensemble 300 000 ms au plus |
| Un pic | plus long que 0 ms, et terminé avant la fin de la durée |
| En parallèle | 1–512 |
| Seuils | 16 au plus, chaque valeur un nombre, 0 ou plus |
Un profil qui ne donne aucune requête est refusé (load.nothing_planned). Les débits sont ceux de la rafale HTTP.
Un profil peut durer aussi longtemps qu’une exécution entière, 300 s — mais la durée limite de l’exécution compte chaque étape : laissez de la place pour le reste de l’expérience.
Combien de requêtes
Les requêtes d’un profil sont son débit cumulé dans le temps :
| Profil | Requêtes |
|---|---|
| Constant, 100/s pendant 1000 ms | 100 |
| Rampe, 0 → 100/s sur 2000 ms | 100 |
| Paliers, à partir de 10/s, +10/s par palier, 3 niveaux de 1000 ms | 60 (10 + 20 + 30) |
| Pic, 10/s avec 100/s à partir de 1000 ms pendant 500 ms, 2000 ms en tout | 65 |
| Aléatoire, 200/s pendant 10 000 ms | 2000 en moyenne |
Le calendrier
La n-ième requête est due à l’instant où le cumul du profil atteint n — la première tout de suite. Chaque instant est calculé à partir du début de la charge : un réveil tardif ne décale donc jamais les requêtes suivantes, et le débit que décrit le profil est bien le débit demandé.
Aléatoire tire au hasard les intervalles entre les arrivées, à partir de la graine de l’exécution : la même graine donne les mêmes instants, si bien qu’une charge aléatoire peut être reproduite exactement. Voir graines.
Requêtes manquées. Au plus En parallèle requêtes sont en cours. Quand toutes attendent encore leur réponse, la requête suivante attend qu’une place se libère. Si elle devait partir plus de 50 ms après son instant, elle n’est pas envoyée en retard : elle est sautée et comptée comme manquée, avec toutes les autres requêtes devenues dues entre-temps, et la charge continue avec la première encore à l’heure. Beaucoup de requêtes manquées signifient que le serveur, ou En parallèle, n’a pas pu suivre le profil.
Pendant l’exécution
Une fois par seconde, la chronologie affiche l’étape avec l’état Sous charge, les secondes écoulées, les requêtes envoyées, le débit de la dernière seconde, le p95 jusqu’ici et les requêtes échouées. Le bouton Arrêter met fin à la charge immédiatement et abandonne les requêtes en cours ; un échec dans une autre branche y met fin en moins d’une seconde.
Ce qui est mesuré
Après la dernière réponse, l’étape dispose de ses mesures, conservées dans son dernier événement de la chronologie et dans le rapport d’exécution :
| Mesure | Quoi |
|---|---|
| planned | les requêtes auxquelles correspond le profil (Aléatoire : en moyenne) |
| sent | les requêtes qui ont reçu une réponse ou ont échoué |
| ok | celles qui ont reçu une réponse de statut 2xx |
| failed | tout autre statut, ou aucune réponse |
| missed | dues alors que toutes les places étaient occupées, et sautées |
| rps | requêtes envoyées par seconde : sent ÷ la durée du profil — ou ÷ le temps jusqu’au départ de la dernière requête, s’il est plus long |
| error_rate | failed, en % de sent |
| min, mean, max | la requête la plus rapide, la moyenne et la plus lente, ms |
| p50, p90, p95, p99 | la latence à laquelle ou sous laquelle se trouvaient 50, 90, 95 et 99 % des requêtes, ms |
| received_bytes | les octets de corps reçus au total |
| statuses | les requêtes par statut (200, 503) et, faute de statut, par cause (timeout, refused, reset …) |
| seconds | chaque seconde du profil : requêtes envoyées, échouées, leur latence moyenne |
| histogram | les requêtes par latence, jusqu’à 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10 000 ms, et au-delà |
La latence d’une requête va de son envoi à la lecture complète de sa réponse, et une requête échouée compte avec le temps qu’elle a mis à échouer. Les percentiles sont lus dans des classes logarithmiques larges de 1 % et sont exacts à 0,5 % près, quelle que soit la durée de la charge.
Seuils
Un seuil est une ligne composée d’une Mesure, d’une Comparaison et d’une Valeur ; le bouton Seuil en ajoute un.
| Mesure | Unité |
|---|---|
| p50, p90, p95, p99 | ms |
| Moyenne, Plus lente | ms |
| Erreurs | % des requêtes envoyées |
| Débit | requêtes par seconde atteintes |
| Manquées | requêtes |
La Comparaison est l’un des opérateurs <, ≤, >, ≥. Quelques seuils courants :
| Mesure | Comparaison | Valeur | L’étape échoue quand |
|---|---|---|---|
| p95 | < | 300 | une requête sur vingt ou plus a pris 300 ms ou davantage |
| Erreurs | < | 1 | 1 % des requêtes ou plus ont échoué |
| Débit | ≥ | 180 | le serveur n’a pas pu absorber 180 requêtes par seconde |
| Manquées | ≤ | 0 | une seule requête a dû être sautée |
Dans un fichier, un seuil s’écrit { "metric": "p95_ms", "op": "lt", "value": 300 } ; les mesures sont p50_ms, p90_ms, p95_ms, p99_ms, mean_ms, max_ms, error_rate, rps et missed, les comparaisons lt, le, gt et ge.
Les seuils sont lus après la dernière réponse, dans leur ordre. L’étape échoue sur le premier qui n’est pas respecté (load.threshold), son message donnant le seuil et la valeur mesurée, et l’exécution échoue avec elle. Sans seuils, une charge réussit quoi qu’elle ait mesuré. Quand l’échec d’une autre branche a mis fin à la charge plus tôt, c’est cet échec qui fait échouer l’exécution, pas un seuil.
Le résultat
Quand l’étape réussit, la chronologie la résume : les requêtes, le débit, le p95 et la part d’échecs. Sélectionnez le nœud : ses propriétés affichent Charge de la dernière exécution —
- chaque seuil, ✓ Respecté ou ✕ Non respecté, avec la valeur mesurée ;
- Envoyées, Req/s, Erreurs avec leur part, Manquées ;
- p50, p90, p95, p99, Moy., Max ;
- Chaque seconde : les requêtes de chaque seconde, les échouées en rouge, et leur latence moyenne sous forme de courbe ;
- Latences : combien de requêtes ont pris combien de temps ;
- les statuts et les causes, chacun avec son nombre.
La ligne de commande affiche les mêmes chiffres et le verdict de chaque seuil ; voir signallab run.
Comparer deux exécutions
- Exécutez l’expérience deux fois, ou plus.
- Dans la chronologie, appuyez sur Comparer. Le bouton est là dès qu’une exécution a enregistré son rapport, et il est désactivé pendant qu’une exécution est en cours.
- La dernière exécution est dans Après, la précédente dans Avant ; chacune des deux listes permet d’en choisir une autre.
Les listes contiennent les exécutions de cette expérience — d’après son nom — tirées des rapports du dossier de données, la plus récente en premier, 50 au plus : chacune avec sa date et son heure, sa façon de se terminer et sa graine. Les exécutions lancées depuis la ligne de commande y figurent aussi si elle a utilisé le même dossier de données. Renommer l’expérience démarre un nouvel historique.
Pour chaque étape de charge, appariée par nœud, un tableau donne chaque mesure dans les colonnes Avant, Après et Écart, dans l’unité et en %. Un écart de 5 % ou plus dans le mauvais sens — plus lent, plus d’erreurs, plus de requêtes manquées, un débit plus faible — est une régression et s’affiche en rouge ; passer de rien à quelque chose compte aussi. Sous le tableau, le verdict de chaque seuil dans les deux exécutions. Une étape de charge que seule l’une des exécutions possède est marquée seulement avant ou seulement après, sans écarts. Pour des exécutions sans étape de charge, le tableau indique Aucune étape de charge dans ces exécutions.
Depuis un script, experiment_runs liste les exécutions et experiment_compare en compare deux, d’après le nom de fichier de leur rapport ; signallab mcp offre la même chose à un assistant (MCP).
Vérifications après une charge
Une charge ne laisse pas de réponse à elle : elle est mesurée, pas vérifiée. Une vérification ou un nœud Extraire une valeur placé après elle a besoin d’une autre requête sans charge avant lui sur chaque chemin, sinon l’expérience ne s’exécute pas (graph.needs_http). Pour vérifier une réponse de l’API sous charge, placez un nœud Requête HTTP ordinaire après la charge, ou dans une branche parallèle à côté d’elle.
Le bouton Envoyer maintenant sur un nœud sous charge envoie sa requête une seule fois.