Vous voulez savoir comment votre API se comporte à exactement 500 requêtes par seconde, et non « aussi vite que N threads peuvent l'assaillir ». La plupart des outils de charge fixent la concurrence et laissent le taux de requêtes flotter. Vegeta fait l'inverse : vous définissez le taux, et il envoie ce nombre de requêtes par seconde, quelle que soit la réponse du serveur. Cette différence est importante lorsque vous vous souciez du chiffre utilisé dans la feuille de résultats, du débit à une charge cible et de la latence que vous promettriez réellement dans un SLO.
bouton
Qu'est-ce que Vegeta
Vegeta est un outil de test de charge HTTP en ligne de commande écrit en Go. Il est également utilisable comme bibliothèque Go, mais ce tutoriel se concentre sur l'interface CLI. L'idée principale est un taux de requêtes constant. Vous dites à Vegeta « envoyer 100 requêtes par seconde pendant 30 secondes », et il maintient ce rythme en ajoutant des workers si nécessaire. Si le serveur ralentit, Vegeta continue d'émettre de nouvelles requêtes selon le calendrier au lieu d'attendre que les anciennes se terminent.
Cette conception vous offre un test de charge en modèle ouvert. Le trafic réel arrive à son propre rythme ; les utilisateurs ne marquent pas de pause et n'attendent pas votre endpoint lent avant que l'utilisateur suivant n'apparaisse. Un outil basé sur le taux correspond à ce comportement.
Charge basée sur le taux vs charge basée sur la concurrence
Voici la distinction qui déroute souvent les gens.
Un outil basé sur la concurrence (un pool fixe de threads ou d'utilisateurs virtuels, chacun bouclant requête-réponse) utilise un modèle fermé. Lorsque le serveur ralentit, la boucle s'arrête, de sorte que le taux de requêtes réel diminue. Vous avez demandé une charge, mais l'outil s'est discrètement retiré. Cela masque l'accumulation que vous verriez en production.
Un outil basé sur le taux comme Vegeta utilise un modèle ouvert. Vous fixez le taux d'arrivée. Si le serveur ne peut pas suivre, les requêtes s'accumulent, la latence augmente et le rapport le montre. Vous obtenez une image honnête de ce qui se passe lorsque la demande dépasse la capacité.
Aucun modèle n'est incorrect. Utilisez la concurrence lorsque vous voulez savoir « combien d'utilisateurs simultanés puis-je gérer ». Utilisez un modèle de taux lorsque vous voulez savoir « ce qui se passe à 2 000 requêtes par seconde ». Vegeta est le deuxième type. Pour une vue d'ensemble plus large de l'espace des outils, consultez les meilleurs outils de test de charge d'API.
Installer Vegeta
Choisissez l'option qui correspond à votre configuration.
Homebrew sur macOS :
brew update && brew install vegeta
Autres gestionnaires de paquets :
# MacPorts
port install vegeta
# Arch Linux
pacman -S vegeta
# FreeBSD
pkg install vegeta
Depuis la source avec Go installé :
git clone https://github.com/tsenart/vegeta
cd vegeta
make vegeta
Vous pouvez également télécharger un binaire précompilé depuis la page des versions de GitHub. Confirmez l'installation :
vegeta --help
Le pipeline principal
Vegeta est construit autour des tubes Unix. Une cible entre, une attaque s'exécute, et un rapport sort. L'exécution utile la plus simple est une seule ligne :
echo "GET http://localhost:8080/" | vegeta attack -duration=5s -rate=100 | vegeta report
Lisez cela de gauche à droite :
echoécrit une cible (une méthode et une URL) sur la sortie standard.vegeta attacklit cette cible depuis l'entrée standard et lance 100 requêtes par seconde pendant 5 secondes. Cela représente un total de 500 requêtes.vegeta reportlit le flux de résultats binaires et affiche un résumé.
L'option -rate prend les requêtes par unité de temps. -rate=100 et -rate=100/1s signifient la même chose. -rate=50/500ms signifie 50 requêtes toutes les 500 millisecondes. Définir -rate=0 supprime la limite et envoie aussi vite que possible, ce qui est un test entièrement différent.
Un rapport textuel ressemble à ceci :
Requests [total, rate, throughput] 500, 100.20, 100.18
Duration [total, attack, wait] 4.991s, 4.990s, 1.2ms
Latencies [min, mean, 50, 90, 95, 99, max] 412us, 1.3ms, 1.1ms, 1.9ms, 2.4ms, 5.1ms, 12ms
Bytes In [total, mean] 128500, 257.00
Bytes Out [total, mean] 0, 0.00
Success [ratio] 100.00%
Status Codes [code:count] 200:500
Error Set:
Lisez d'abord la ligne de latence. La colonne 50 est la médiane. La colonne 99 est la queue : 1 pour cent des requêtes ont été plus lentes que cela. Les queues sont là où les utilisateurs ressentent de la douleur, donc une moyenne saine avec un 99e centile médiocre reste un problème. Vérifiez ensuite Success [ratio] et Status Codes. Un taux de succès de 100 pour cent avec tous les codes 200 signifie que le serveur a maintenu la charge. Tout code 5xx ou un Error Set non vide signifie qu'il a commencé à flancher.
Enregistrer les résultats, puis les rapporter de plusieurs façons
Envoyer directement vers report est suffisant pour un aperçu rapide. Pour tout ce que vous revisiterez, enregistrez d'abord les résultats bruts dans un fichier, puis générez tous les rapports que vous souhaitez à partir de ce fichier unique.
echo "GET http://localhost:8080/" | \
vegeta attack -duration=10s -rate=200 -output=results.bin
Maintenant, l'exécution est capturée dans results.bin. Produisez un rapport textuel :
vegeta report results.bin
Produisez du JSON structuré pour un tableau de bord ou une comparaison entre les exécutions :
vegeta report -type=json results.bin > metrics.json
Produisez un histogramme de latence avec les intervalles de votre choix :
vegeta report -type='hist[0,2ms,5ms,10ms,25ms,100ms]' results.bin
L'histogramme compte le nombre de requêtes tombant dans chaque bande de latence. C'est un moyen rapide de voir si la latence est étroitement regroupée ou étendue sur une large plage.
Le format de fichier des cibles
Les API réelles nécessitent plus qu'une seule requête GET. Déplacez vos cibles dans un fichier et passez-le avec -targets. Le format HTTP par défaut est basé sur des lignes et est lisible.
Créez targets.txt :
GET http://localhost:8080/api/users
POST http://localhost:8080/api/users
Content-Type: application/json
@./payload.json
GET http://localhost:8080/api/users/42
Quelques règles pour que cela fonctionne :
- La première ligne de chaque cible est
MÉTHODE URL. - Les lignes d'en-tête suivent directement sous la ligne de méthode, une
Clé: Valeurpar ligne. - Une ligne commençant par
@nomme un fichier dont le contenu devient le corps de la requête. - Une ligne vide sépare une cible de la suivante.
- Les lignes commençant par
#sont des commentaires.
Mettez votre corps JSON dans payload.json :
{ "name": "Ada", "role": "engineer" }
Lancez l'attaque contre le fichier :
vegeta attack -targets=targets.txt -rate=50 -duration=30s | vegeta report
Vegeta parcourt les cibles dans l'ordre et continue de boucler jusqu'à la fin de la durée. Vous pouvez également ajouter des en-têtes globaux sur la ligne de commande avec -header, ce qui est pratique pour l'authentification :
vegeta attack -targets=targets.txt -rate=50 -duration=30s \
-header="Authorization: Bearer $TOKEN" | vegeta report
Pour les exécutions programmatiques ou à volume élevé, Vegeta lit également un format de cible JSON. Chaque ligne est un objet JSON, et vous le sélectionnez avec -format=json :
{"method": "GET", "url": "http://localhost:8080/api/users"}
{"method": "POST", "url": "http://localhost:8080/api/users", "header": {"Content-Type": ["application/json"]}, "body": "eyJuYW1lIjoiQWRhIn0="}
Le champ body est encodé en base64. Ce format se prête bien au streaming, vous pouvez donc générer des cibles à la volée et les introduire directement avec -lazy pour une meilleure efficacité mémoire.
Graphiques et histogrammes
Un seul chiffre masque les tendances. Si la latence se dégrade à mi-parcours d'une exécution, vous voulez voir la courbe. La commande plot de Vegeta transforme un flux de résultats en une page HTML interactive :
vegeta attack -targets=targets.txt -rate=100 -duration=60s | \
vegeta plot > plot.html
Ouvrez plot.html dans un navigateur. Vous obtenez un graphique de série chronologique de la latence tout au long de l'exécution, de sorte qu'une augmentation lente ou un pic en cours de test est évident. Vous pouvez représenter plusieurs exécutions ensemble pour comparer les niveaux de charge :
vegeta attack -rate=50 -duration=30s -targets=targets.txt -output=50qps.bin
vegeta attack -rate=100 -duration=30s -targets=targets.txt -output=100qps.bin
vegeta plot 50qps.bin 100qps.bin > compare.html
Pour les environnements sans interface graphique, ignorez le graphique et exportez un histogramme ou le CSV brut avec encode :
vegeta encode -to=csv results.bin > results.csv
Quand utiliser Vegeta
Utilisez Vegeta lorsque la question porte sur le taux et la capacité :
- Vous avez besoin du débit et de la latence pour un objectif spécifique de requêtes par seconde.
- Vous voulez trouver le taux à partir duquel la latence ou le taux d'erreur commence à augmenter.
- Vous comparez deux versions ou deux configurations d'infrastructure sous une charge identique et reproductible.
- Vous voulez un outil scriptable qui s'intègre dans un pipeline de shell et une tâche de CI sans interface graphique.
C'est un instrument ciblé. Il envoie des requêtes HTTP à un certain rythme et mesure la réponse du serveur. Il ne scripte pas des parcours utilisateur en plusieurs étapes avec une logique de branchement, et il ne valide pas les corps de réponse au-delà des codes d'état. Cette focalisation est une caractéristique ; elle maintient l'outil léger et les résultats clairs.
Si vous le comparez à d'autres outils de test, les comparaisons dans le test de charge k6 et le test de charge JMeter couvrent les alternatives de modèle de concurrence. Pour les concepts et métriques sous-jacents, le tutoriel sur les tests de performance d'API est une bonne introduction.
Où s'intègrent les tests fonctionnels
Le test de charge répond à la question « est-ce assez rapide ? ». Il ne répond pas à la question « est-ce correct ? ». Une exécution Vegeta peut rapporter 100 % de codes 200 alors que l'endpoint renvoie le mauvais utilisateur, un prix obsolète ou un champ JSON mal formé. Chacune de ces réponses est un 200 rapide et réussi, du point de vue d'un outil de charge.
L'exactitude nécessite une vérification différente : des assertions sur le corps de la réponse, le schéma et les règles métier. C'est le test fonctionnel, et il doit être effectué avant et en parallèle de vos exécutions de charge. La bonne pratique consiste à valider que l'API est correcte, puis à mesurer ses performances sous charge.
C'est là qu'Apidog complète un outil comme Vegeta plutôt que de le concurrencer. Dans Apidog, vous construisez des scénarios de test avec des assertions visuelles sur le statut, les en-têtes et les champs JSON, enchaînez des requêtes et les exécutez à partir de fichiers de données. Vous confirmez que l'API renvoie les données correctes. Vegeta confirme ensuite qu'elle reste rapide lorsque ce chemin correct est sollicité des centaines de fois par seconde. Deux outils, deux questions.
Apidog propose également une CLI sans interface graphique afin que ces scénarios fonctionnels s'exécutent dans le même pipeline de CI que votre étape de charge. Installez-le avec Node :
npm install -g apidog-cli
Ensuite, exécutez un scénario ou une suite enregistrée par ID, avec des rapporteurs pour votre pipeline :
apidog run --access-token "$APIDOG_ACCESS_TOKEN" \
-t <scenarioOrSuiteId> \
-e <environmentId> \
-r cli,html,junit
L'option -t prend l'ID du scénario, du dossier ou de la suite, -e prend l'ID de l'environnement, et -r sélectionne un ou plusieurs rapporteurs (cli, html, json, junit). La sortie junit s'intègre dans la plupart des tableaux de bord de CI. Consultez le tutoriel de ligne de commande Apidog CLI pour une exécution pas à pas, et le guide de pipeline CI/CD pour un workflow prêt à copier-coller. Exécutez d'abord la validation fonctionnelle, puis laissez Vegeta mesurer les endpoints qui ont réussi.
FAQ
Vegeta prend-il en charge les requêtes POST avec un corps ?
Oui. Dans le fichier de cibles HTTP, mettez la méthode et l'URL sur la première ligne, ajoutez un en-tête Content-Type et référencez un fichier de corps avec @./payload.json. Au format JSON, définissez les champs method, url et un champ body encodé en base64.
Que fait -rate=0 ?
Cela supprime la limite de taux et envoie les requêtes aussi vite que les workers et les connexions le permettent. Il s'agit d'un test de débit maximal, différent d'un test à taux constant contrôlé. Pour des mesures de capacité reproductibles, définissez un taux explicite.
Comment lire les centiles de latence ?
La ligne de latence du rapport affiche le minimum, la moyenne et les 50e, 90e, 95e, 99e et maximum centiles. Concentrez-vous sur les 95e et 99e. Ils décrivent la "longue traîne" lente que les utilisateurs réels rencontrent, et qu'une simple moyenne peut masquer.
Vegeta peut-il vérifier que mon API renvoie des données correctes ?
Non. Il mesure le débit, la latence et les codes d'état. Il ne fait pas d'assertions sur les corps de réponse ou les schémas. Associez-le à un outil de test fonctionnel pour la justesse, puis utilisez Vegeta pour le taux et la latence.
Comment exécuter Vegeta en CI ?
C'est un binaire unique qui lit l'entrée standard et écrit les résultats, il s'intègre donc dans n'importe quelle étape de shell. Enregistrez les résultats avec -output, puis générez un rapport texte ou JSON comme artefact de build. Ajoutez une "porte" fonctionnelle, telle que l'Apidog CLI, avant l'étape de charge afin de ne mesurer que les endpoints qui ont déjà passé leurs assertions.
