wrk : Comment faire un test de charge API en ligne de commande

Apprenez à tester la charge d'une API avec wrk depuis la ligne de commande : l'installation, les options de threads et de connexions, la lecture de la sortie de latence, et les requêtes POST via Lua.

Ashley Innocent

Ashley Innocent

6 July 2026

wrk : Comment faire un test de charge API en ligne de commande

Apidog pour les entreprises

Déploiement sur site

SSO & RBAC

Conforme SOC 2

Découvrir Apidog Enterprise

Vous avez déployé un endpoint. Il fonctionne dans votre navigateur. Mais vous n'avez aucune idée de ce qui se passe lorsque 400 personnes l'appellent simultanément. La latence reste-t-elle stable, ou le quatre-vingt-dix-neuvième centile explose-t-il ? La machine peut-elle gérer 1 000 requêtes par seconde, ou s'effondre-t-elle à 300 ?

wrk répond à ces questions. C'est un petit outil en ligne de commande qui envoie beaucoup de trafic HTTP à une URL et indique la vitesse à laquelle le serveur a répondu sous cette charge.

bouton

Qu'est-ce que wrk et quand l'utiliser

wrk est un outil moderne de benchmarking HTTP. Il génère de la charge à partir d'une seule machine multi-cœur et mesure la latence et le taux de requêtes renvoyés par le serveur. Il utilise le multithreading et une boucle d'événements évolutive (epoll sur Linux, kqueue sur macOS), de sorte qu'une seule instance peut générer beaucoup de trafic sans avoir besoin d'une flotte de machines de charge.

Utilisez wrk lorsque vous souhaitez obtenir des chiffres de performance bruts :

wrk est un outil de benchmarking, pas une suite de tests. Il mesure la vitesse. Il ne vérifie pas que le corps JSON est correct, que le code de statut est 200, ou que le contrat d'API a été respecté. Gardez cette distinction à l'esprit. Nous y reviendrons vers la fin, car cela change la façon dont vous intégrez wrk dans un véritable workflow de test. Si vous voulez d'abord avoir une vue d'ensemble, ce guide sur le test de charge d'API couvre les concepts que wrk met en pratique.

Installation de wrk

macOS

Homebrew propose un binaire précompilé, ce qui est le chemin le plus simple :

brew install wrk

Ceci est important sur Apple Silicon. La compilation à partir des sources peut rencontrer des problèmes avec LuaJIT ARM64, le binaire Homebrew vous épargne donc les tracas.

Linux (compilation à partir des sources)

Il n'y a pas de package apt officiel, vous devez donc le compiler. Installez d'abord la chaîne d'outils et les en-têtes OpenSSL :

sudo apt-get install build-essential libssl-dev git -y

Ensuite, clonez et compilez :

git clone https://github.com/wg/wrk.git
cd wrk
make

Ceci produit un exécutable wrk dans le répertoire actuel. Déplacez-le dans votre PATH afin de pouvoir l'appeler depuis n'importe où :

sudo cp wrk /usr/local/bin

Confirmez qu'il fonctionne :

wrk --version

La commande de base

Voici la forme de chaque exécution de wrk :

wrk -t12 -c400 -d30s http://127.0.0.1:8080/index.html

Quatre choses se passent. Analysons les drapeaux (options).

Deux autres drapeaux (options) que vous utiliserez constamment :

Une exécution que vous utiliserez souvent ressemble à ceci :

wrk -t8 -c200 -d30s --latency http://localhost:3000/api/users

Huit threads, 200 connexions, 30 secondes, avec la distribution complète de la latence affichée à la fin.

Lecture de la sortie

wrk affiche un rapport compact. Voici un exemple réel d'exécution contre un petit service :

Running 5s test @ http://10.135.232.163:3000
  2 threads and 5 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     3.82ms    2.64ms  26.68ms   85.81%
    Req/Sec   550.90    202.40     0.98k    68.00%
  5494 requests in 5.01s, 1.05MB read
Requests/sec:   1096.54
Transfer/sec:    215.24KB

Lisez-le de bas en haut, car les deux dernières lignes sont les informations principales.

Requêtes/sec est le débit : combien de requêtes le serveur a complétées par seconde en moyenne. Ici, c'est 1 096. C'est le chiffre que vous comparez entre les exécutions et entre les changements de code.

Transfert/sec est la bande passante : la quantité de données déplacées par seconde. Utile lorsque les charges utiles sont importantes ou si vous soupçonnez d'être limité par la bande passante plutôt que par le CPU.

Maintenant, le tableau Statistiques des threads, qui décrit la distribution, pas seulement la moyenne :

La colonne +/- Stdev vous indique le pourcentage d'échantillons qui se situent à l'intérieur d'un écart-type. Des pourcentages plus faibles signifient une dispersion plus large et moins prévisible.

La ligne 5494 requests in 5.01s confirme le volume total que l'exécution a réellement généré.

Lorsque vous ajoutez --latency, wrk affiche un bloc de percentiles afin que vous puissiez voir directement la queue de distribution :

  Latency Distribution
     50%    3.21ms
     75%    4.86ms
     90%    7.09ms
     99%   14.13ms

Le 99e centile est le chiffre à surveiller. Si 99 % des requêtes se terminent en 14 ms mais que votre moyenne est de 3,82 ms, un utilisateur sur cent attend bien plus longtemps que ce que la moyenne suggère. Les moyennes mentent sur les queues de distribution. Les percentiles non.

Envoyer des requêtes POST et des en-têtes personnalisés avec un script Lua

Par défaut, wrk envoie des requêtes GET. Pour envoyer un POST, ajouter un corps de requête ou définir des en-têtes personnalisés, vous passez un script Lua avec -s.

Créez un fichier nommé post.lua :

wrk.method = "POST"
wrk.body   = '{"name": "Ada", "role": "engineer"}'
wrk.headers["Content-Type"] = "application/json"

Trois champs font le travail. wrk.method définit le verbe HTTP. wrk.body définit le corps de la requête. wrk.headers est un tableau où chaque clé est un nom d'en-tête.

Exécutez-le en pointant -s vers le script :

wrk -t4 -c100 -d30s -s post.lua --latency http://localhost:3000/api/users

Pour un POST encodé sous forme de formulaire au lieu de JSON, le dépôt wrk fournit cet exemple exact :

wrk.method = "POST"
wrk.body   = "foo=bar&baz=quux"
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"

Vous pouvez également définir des en-têtes avec le drapeau -H pour des cas plus simples, sans script :

wrk -t4 -c100 -d30s -H "Authorization: Bearer TOKEN123" --latency http://localhost:3000/api/protected

Utilisez -H pour un ou deux en-têtes. Utilisez un script Lua lorsque vous avez besoin d'un corps de requête, d'une méthode autre que GET, ou d'une logique par requête.

Les limites : wrk ne vérifie pas la correction

Voici la partie que les gens oublient. wrk vous indique à quelle vitesse le serveur a répondu. Il ne vous dit pas si la réponse était correcte.

Dirigez wrk vers un endpoint qui renvoie un code HTTP 500 à chaque requête, et vous obtiendrez un rapport d'apparence propre avec un nombre élevé de requêtes par seconde. wrk compte un échange HTTP complété. Il n'effectue pas d'assertion sur le code de statut, ne valide pas le corps de la réponse par rapport à un schéma, et ne confirme pas que l'API a fait ce qu'elle était censée faire. Les erreurs peuvent même sembler rapides, car un serveur qui rejette les requêtes tôt fait moins de travail par requête.

Donc, wrk répond à la question « est-ce assez rapide sous charge ? » Il ne peut pas répondre à « est-ce correct ? » Les deux questions sont importantes et nécessitent des outils différents. Un chiffre de charge sur un endpoint défectueux est un chiffre auquel vous ne devriez pas faire confiance. C'est précisément pourquoi les équipes associent un outil de benchmarking à une suite de tests fonctionnels. L'un prouve la vitesse. L'autre prouve le comportement.

Où Apidog et les tests fonctionnels s'intègrent

Le workflow propre se compose de deux couches, exécutées dans l'ordre.

Premièrement, validez le comportement. Avant de vous soucier de la rapidité d'un endpoint, confirmez qu'il est correct. Dans Apidog, vous construisez des scénarios de test qui envoient de vraies requêtes et effectuent des assertions sur ce qui est renvoyé : codes de statut, champs JSON, schéma de réponse et logique métier. Vous pouvez enchaîner des requêtes, passer des données entre les étapes et exécuter le même scénario dans différents environnements. C'est cette couche qui détecte l'erreur 500 que wrk mesurerait joyeusement.

Ensuite, mesurez le débit. Une fois le comportement vérifié, exécutez wrk sur les mêmes endpoints pour voir comment ils tiennent le coup sous concurrence et charge soutenue. Apidog dispose également de tests de performance intégrés si vous préférez garder les tests fonctionnels et de charge au même endroit, mais wrk est un excellent outil dédié au benchmarking en ligne de commande pur.

La couche fonctionnelle s'exécute en intégration continue (CI), pas seulement sur votre ordinateur portable. L'interface CLI d'Apidog est sans interface graphique (headless), elle peut donc être intégrée à n'importe quelle étape de pipeline pouvant exécuter Node. Installez-la :

npm install -g apidog-cli

Ensuite, exécutez un scénario ou une suite de tests enregistrés par ID :

apidog run \
  --access-token "$APIDOG_ACCESS_TOKEN" \
  -t <scenarioOrSuiteId> \
  -e <environmentId> \
  -r cli,html,junit

-t est l'ID du scénario, du dossier ou de la suite à exécuter. -e est l'ID de l'environnement. -r sélectionne les formats de rapport, un ou plusieurs parmi cli, html, json et junit. La sortie JUnit s'intègre directement dans la plupart des systèmes CI pour le filtrage succès/échec. Pour les exécutions basées sur les données, ajoutez -d (ou --iteration-data) avec un chemin de fichier ou un ID de données de test pour itérer le même scénario sur plusieurs lignes d'entrée.

L'interface CLI exécute les scénarios et suites Apidog enregistrés. Elle est sans interface graphique (headless), ce n'est pas un expéditeur de requêtes interactif, et ce n'est pas un générateur de charge. C'est la porte de la correction. wrk est l'indicateur de vitesse. Exécutez la porte de la correction dans votre pipeline (consultez ce guide pas à pas CLI CI/CD ou le guide GitHub Actions pour la configuration à copier-coller), puis effectuez le benchmarking avec wrk lorsque vous avez besoin des chiffres de débit. La référence complète de la CLI couvre le reste des drapeaux (options).

FAQ

Quelle est la différence entre wrk et ab (ApacheBench) ? Les deux envoient une charge HTTP et rapportent le nombre de requêtes par seconde. wrk est multithreadé et utilise une boucle d'événements, il génère donc plus de charge à partir d'une seule machine et gère mieux la concurrence élevée. ab est monotâche (single-threaded). Pour une charge lourde à partir d'une seule machine, wrk est généralement plus performant. Aucun des deux ne vérifie la correction de la réponse.

Combien de threads et de connexions dois-je utiliser ? Commencez avec un thread par cœur de CPU, et définissez les connexions au niveau de concurrence que vous souhaitez simuler. Si vous avez 8 cœurs et que vous voulez simuler 200 clients concurrents, essayez -t8 -c200. Surveillez la machine cliente. Si wrk lui-même est limité par le CPU, vos chiffres reflètent la limite du générateur de charge, et non celle du serveur. Augmentez le nombre de connexions jusqu'à ce que le débit cesse d'augmenter.

wrk peut-il tester des endpoints HTTPS ? Oui. Dirigez-le vers une URL https:// et wrk gère le TLS. C'est pourquoi la compilation Linux nécessite libssl-dev. Les handshakes TLS ajoutent un coût CPU aux deux extrémités, attendez-vous donc à un débit brut plus faible pour HTTPS que pour HTTP simple.

wrk valide-t-il le corps de la réponse ou le code de statut ? Non. wrk compte les échanges HTTP complétés et mesure le temps. Il n'effectue pas d'assertion sur les codes de statut ou les corps de réponse, donc un endpoint renvoyant des erreurs peut toujours afficher un nombre élevé de requêtes par seconde. Utilisez une suite de tests fonctionnels, telle qu'une exécutée via l'interface CLI d'Apidog, pour vérifier la correction, puis utilisez wrk pour le débit.

Combien de temps doit durer un test de charge ? Assez longtemps pour dépasser les effets de démarrage comme les caches froids et la compilation JIT. Quelques secondes suffisent pour une vérification rapide, mais 30 secondes à quelques minutes donnent des chiffres plus stables et révèlent une dégradation qui n'apparaît que sous une charge soutenue. Utilisez -d30s comme valeur par défaut raisonnable et prolongez-la lorsque vous recherchez des fuites lentes.

Pratiquez le Design-first d'API dans Apidog

Découvrez une manière plus simple de créer et utiliser des API