Guides

Test de charge gRPC : outils, mise en place et mesures

7 min de lecture

Un test de charge gRPC demande un outil qui parle HTTP/2 et Protocol Buffers : k6 et ghz le font d’origine, JMeter a besoin d’un plugin, la prise en charge de gRPC dans Gatling est limitée dans son édition gratuite, et avec Locust vous devez intégrer vous-même un client gRPC. Comptez les résultats par statut gRPC, pas par statut HTTP, car les appels en échec arrivent quand même en HTTP 200, et vérifiez que la charge atteint chaque backend.

Aucun test gRPC n’a été exécuté pour cet article. Les faits sur les outils viennent de la documentation et des dépôts de chaque projet, vérifiés le 16 octobre 2026 ; les faits sur LoadFocus viennent de son code.

OutilPrise en charge de gRPCLit l’API depuisContrôle de la cadence
k6Intégré (k6/net/grpc), appels unaires et streamsFichiers .proto ou réflexion serveurExécuteurs arrival-rate
ghzOutil en ligne de commande dédié à gRPC.proto, protoset ou réflexion serveur--rps et plannings de charge
JMeterPlugin tiers (jmeter-grpc-request)Un dossier de fichiers .protoThread Groups et timers
GatlingComposant gRPC séparé ; édition gratuite limitée à 5 utilisateurs, 5 minutesCode généré depuis les .proto avec protocProfils d’injection
LocustPas de client intégré ; en envelopper un et remonter les appelsVotre client gRPC PythonTemps d’attente, constant_throughput

Pourquoi gRPC demande-t-il un autre test de charge que REST ?

gRPC passe par HTTP/2, envoie des Protocol Buffers binaires au lieu de JSON, place le résultat d’un appel dans un trailer plutôt que dans le statut HTTP, et multiplexe de nombreux appels sur une seule connexion. Chacun de ces points change la façon d’écrire le test ou d’en lire les résultats.

L’article sur la répartition de charge gRPC énumère les caractéristiques de HTTP/2 qui comptent ici : un protocole binaire, de nombreuses requêtes multiplexées sur une connexion et la compression des en-têtes, avec par-dessus des messages Protobuf fortement typés (vérifié le 16 octobre 2026). Un outil qui n’envoie que du JSON sur HTTP/1.1 ne peut pas appeler une méthode gRPC : vérifiez d’abord la prise en charge du protocole.

Quel outil choisir ?

Prenez k6 si vous voulez des scénarios, des checks et des seuils écrits en code ; prenez ghz pour un benchmark rapide d’une méthode en ligne de commande. Tournez-vous vers JMeter, Gatling ou Locust quand votre équipe y fait déjà tout le reste.

  • k6. Le module k6/net/grpc charge les définitions Protobuf, se connecte, fait des appels unaires avec invoke et ouvre des streams. Il rapporte grpc_req_duration et le nombre de messages des streams dans ses métriques.
  • ghz. Un outil de benchmark en ligne de commande réservé à gRPC. Ses options incluent --rps, --concurrency, --total et --duration, et si vous ne passez ni --proto ni --protoset, il tente la réflexion serveur. La dernière version est v0.121.0 (vérifié le 16 octobre 2026).
  • JMeter. Le cœur de JMeter n’a pas de sampler gRPC ; le plugin jmeter-grpc-request en ajoute un qui lit un dossier de fichiers .proto, sans génération de code (dernier tag v1.2.6, vérifié le 16 octobre 2026).
  • Gatling. Le README de Gatling place gRPC, MQTT et GraphQL sous la Gatling Enterprise Component License, limités en Community Edition à 5 utilisateurs simultanés et à des tests de 5 minutes (vérifié le 16 octobre 2026). Son guide de mise en place gRPC génère du code à partir de vos fichiers .proto avec protoc.
  • Locust. Sa documentation sur le test d’autres systèmes inclut un exemple gRPC : vous enveloppez un client gRPC pour que chaque appel soit remonté à Locust, et constant_throughput cadence une tâche à un nombre maximal d’exécutions par seconde.

Choisissez ghz plutôt que k6 quand vous voulez seulement savoir comment une méthode se comporte à une cadence donnée, sans écrire de script. Choisissez plutôt Locust quand votre équipe écrit en Python et que le test demande une logique plus simple à y écrire.

Comment écrire un test de charge gRPC avec k6 ?

Chargez le fichier .proto dans le code d’initialisation, puis, à chaque itération, connectez-vous, appelez la méthode et vérifiez le statut gRPC. La structure suit l’exemple de la documentation de k6.

import grpc from 'k6/net/grpc';
import { check } from 'k6';

const client = new grpc.Client();
client.load(['protos'], 'hello.proto');

export const options = { vus: 20, duration: '1m' };

export default () => {
  client.connect('grpc.example.com:443');
  const res = client.invoke('hello.Greeter/SayHello', {
    name: 'load test',
  });
  check(res, {
    'status is OK': (r) => r && r.status === grpc.StatusOK,
  });
  client.close();
};

La page de invoke suit la même séquence : chargement, connexion, appel, vérification et fermeture. connect utilise TLS sauf si vous passez plaintext: true, et avec reflect: true il demande son API au serveur au lieu de lire un fichier .proto (paramètres de connexion). Pour tenir une cadence de requêtes plutôt qu’un nombre d’utilisateurs, exécutez la fonction dans un scénario arrival-rate.

Comment faire un benchmark rapide avec ghz ?

Indiquez à ghz la méthode, un corps de requête et une cadence ou un niveau de concurrence, et il affiche un histogramme de latence, des percentiles et un décompte par code de statut. Il convient pour un premier aperçu d’une méthode.

ghz --insecure --proto ./hello.proto \
  --call hello.Greeter.SayHello \
  -d '{"name":"load test"}' \
  --rps 200 -c 50 -z 1m \
  localhost:50051

--rps fixe la cadence visée, répartie entre les workers, -c le nombre de workers, et -z la durée. Retirez --proto pour laisser ghz utiliser la réflexion serveur, si le serveur l’active. La page sur la sortie de ghz montre un exemple de rapport.

Que mesurer dans un test de charge gRPC ?

Mesurez les percentiles de latence des appels, le débit et le nombre de chaque code de statut gRPC. Un taux de réussite au niveau HTTP peut afficher 100 % alors que des appels échouent, car le résultat voyage dans le trailer grpc-status.

La spécification gRPC sur HTTP/2 fixe le statut HTTP à :status 200 et transporte le résultat de l’appel dans des trailers, sous la forme grpc-status et grpc-message. La liste des codes de statut contient ceux qui comptent le plus sous charge :

  • DEADLINE_EXCEEDED (4) : l’échéance a expiré avant la fin de l’appel.
  • RESOURCE_EXHAUSTED (8) : un quota ou une ressource est épuisé.
  • INTERNAL (13) : un invariant interne est rompu, un code réservé aux erreurs graves.
  • UNAVAILABLE (14) : en général passager ; réessayer avec un backoff peut suffire, mais pas toujours sans risque pour les appels non idempotents.

Comptez chacun par palier de charge. Les erreurs d’échéance peuvent grimper alors que les appels réussis semblent encore rapides, parce que les appels lents sont coupés à l’échéance au lieu d’être enregistrés comme lents. Notre guide des critères de réussite d’un test de charge montre comment transformer ces décomptes en seuils.

Pourquoi toute la charge tombe-t-elle sur un seul serveur ?

Parce que gRPC multiplexe de nombreux appels sur une connexion de longue durée, un répartiteur qui travaille par connexion envoie chaque appel de celle-ci au même backend. Un générateur de charge avec peu de connexions peut alors saturer un serveur pendant que les autres restent inactifs.

L’article sur la répartition de charge gRPC explique le mécanisme. Un répartiteur au niveau transport (L3/L4) termine la connexion TCP et en ouvre une autre vers un backend choisi, en copiant les trames HTTP/2 et gRPC entre les deux ; un répartiteur au niveau applicatif (L7) analyse HTTP/2 et peut répartir les streams d’une même connexion cliente entre plusieurs backends. Si vos clients de production passent par un répartiteur L7 ou répartissent côté client, testez par le même chemin et surveillez le CPU et le nombre de requêtes de chaque backend pendant l’exécution.

Peut-on lancer des tests de charge gRPC sur LoadFocus ?

Pas d’une façon que ses rapports montreraient. LoadFocus exécute la version standard de k6 v0.57.0, qui inclut le module gRPC, mais son agent k6 ne transmet aux résultats que les mesures des requêtes HTTP : les appels gRPC généreraient de la charge sans apparaître dans ses graphiques ni dans ses décomptes d’erreurs.

Deux autres limites s’ajoutent. L’import de fichiers k6 accepte les fichiers .js, .ts, .csv, .txt, .json, .env et .properties, pas les fichiers .proto, donc un script devrait se connecter avec reflect: true. Et la voie JMeter est fermée : les agents JMeter de LoadFocus embarquent JMeter 5.6.2 avec des plugins préinstallés qui ne comprennent pas de sampler gRPC, et l’import JMeter n’accepte pas de fichiers JAR de plugin. Pour gRPC, lancez k6 ou ghz sur vos propres machines, et utilisez les scripts k6 sur LoadFocus pour la partie HTTP du même système, où il génère la charge depuis 25 régions.

FAQ

Peut-on tester en charge des appels gRPC en streaming ? Oui, avec k6 et ghz. Le module gRPC de k6 a une classe Stream avec write, end et des gestionnaires d’événements, et ghz a des options pour les intervalles et les durées de streaming. Mesurez les messages envoyés et reçus en plus de la latence des appels.

Faut-il le fichier .proto pour tester en charge un service gRPC ? Pas si le serveur active la réflexion. k6 peut se connecter avec reflect: true, et ghz se rabat sur la réflexion quand vous ne passez ni --proto ni --protoset. Sans réflexion, il vous faut le fichier .proto ou un protoset compilé.

Pourquoi mes erreurs gRPC n’apparaissent-elles pas comme des requêtes en échec ? Parce que le statut HTTP d’un appel gRPC vaut 200 même quand l’appel échoue. Le résultat se trouve dans le trailer grpc-status : vérifiez cette valeur dans votre script et comptez chaque code séparément.

À lire aussi


Les affirmations techniques de cet article n'ont pas été relues de façon indépendante.

LoadFocus team
Écrit par l'équipe LoadFocus, qui fait tourner un service de test de charge dans le cloud.