Tests de brokers

Test de charge MQTT avec JMeter : plugin, thread groups et résultats

Testez la charge d'un broker MQTT avec JMeter : plugin MQTT, thread groups publishers et subscribers, exécution sans GUI et lecture des résultats.

Mis à jour · 9 min de lecture

Test de charge MQTT avec JMeter : plugin, thread groups et résultats

Apache JMeter peut tester la charge d'un broker MQTT dès que vous ajoutez un plugin MQTT : chaque thread JMeter devient un client MQTT qui se connecte, publie ou s'abonne, et les timers, listeners et le rapport HTML de JMeter font le reste. Si votre équipe utilise déjà JMeter pour HTTP, vous gardez ainsi un seul outil, un seul format de rapport et un seul job de CI pour vos tests MQTT.

Ce guide installe le plugin, construit un test plan avec publishers et subscribers, l'exécute sans GUI et explique ce que mesurent réellement les chiffres.

Choisir un plugin MQTT

JMeter n'a aucun sampler MQTT intégré. L'option la plus utilisée est emqx/mqtt-jmeter (publié à l'origine par XMeter). Il ajoute quatre samplers :

SamplerRôle
MQTT ConnectOuvre une connexion (TCP, SSL, WS ou WSS) et la conserve pour le thread
MQTT Pub SamplerPublie sur un topic avec le QoS, le flag retain et le payload choisis
MQTT Sub SamplerS'abonne et échantillonne les messages reçus sur une fenêtre de temps ou un nombre de messages
MQTT DisConnectFerme la connexion du thread

Les samplers Pub et Sub réutilisent la connexion créée par le sampler Connect dans le même thread. S'il n'y a pas encore de connexion, ils échouent immédiatement — exactement ce que vous voulez voir dans le rapport.

Installer JMeter et le plugin

JMeter a besoin d'un runtime Java (Java 8 ou plus récent pour JMeter 5.6). Téléchargez JMeter, puis copiez le jar du plugin depuis la page des releases du projet dans lib/ext :

Installer JMeter 5.6.3 et le plugin MQTT
curl -LO https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-5.6.3.tgz
tar xzf apache-jmeter-5.6.3.tgz

# téléchargez le dernier jar sur https://github.com/emqx/mqtt-jmeter/releases
cp ~/Downloads/mqtt-xmeter-*.jar apache-jmeter-5.6.3/lib/ext/

apache-jmeter-5.6.3/bin/jmeter   # lance la GUI pour construire le plan

Après redémarrage, un clic droit sur un Thread Group → Add → Sampler affiche les quatre samplers MQTT. Utilisez la GUI uniquement pour construire et déboguer le plan ; la vraie charge se lance en ligne de commande.

Avant toute charge, vérifiez que l'hôte, le port et les identifiants fonctionnent avec un seul client dans le client MQTT en ligne. Un mauvais mot de passe sur 500 threads produit 500 erreurs identiques et aucune information utile. Les exemples utilisent broker.connectmq.com, un endpoint partagé prévu pour des vérifications fonctionnelles rapides ; pour le test de charge lui-même, pointez -Jhost et les identifiants vers votre propre instance privée de broker.

Construire le test plan

Un test de télémétrie réaliste comporte deux groupes de clients : des publishers qui envoient les données des appareils et des subscribers qui les consomment. Cette structure donne à chaque publisher son propre topic et son propre subscriber (un pour un), pour mesurer le routage et non le fan-out :

mqtt-load.jmx — arbre du test plan
Test Plan
├── User Defined Variables: HOST, PORT, THREADS, RATE
├── Thread Group "subscribers"   threads=${THREADS}  ramp-up=30 s
│   ├── MQTT Connect           clientId prefix "jm_sub_" + random suffix
│   └── MQTT Sub Sampler       topic testmqtt/jmeter/${__threadNum}/data
├── Thread Group "publishers"    threads=${THREADS}  ramp-up=60 s  duration=600 s
│   ├── Once Only Controller
│   │   └── MQTT Connect       clientId prefix "jm_pub_" + random suffix
│   └── MQTT Pub Sampler       topic testmqtt/jmeter/${__threadNum}/data
│       └── Constant Throughput Timer   ${RATE} samples/min, all active threads
├── tearDown Thread Group → MQTT DisConnect
└── Summary Report (GUI debugging only)

Réglages clés, sampler par sampler :

  • Variables. Définissez HOST comme ${__P(host,broker.connectmq.com)}, PORT comme ${__P(port,1883)}, etc. __P lit une propriété passée avec -J en ligne de commande et retombe sur la valeur par défaut, si bien qu'un seul .jmx sert pour tous les environnements.
  • MQTT Connect. Serveur ${HOST} (sans préfixe tcp://), port ${PORT}, protocole TCP (ou SSL sur le port 8883, WSS sur le 8084), identifiant et mot de passe issus des propriétés, keep alive identique à celui de vos appareils. Activez le suffixe aléatoire du client ID : deux threads avec le même client ID s'éjecteraient mutuellement du broker.
  • Once Only Controller. Le thread publisher se connecte uniquement à sa première itération, puis répète le Pub sampler. Sans lui, chaque itération ouvrirait une nouvelle connexion et vous testeriez le débit de connexions au lieu du throughput.
  • MQTT Pub Sampler. QoS 1, retain désactivé, type de payload "random string with fixed length" à la taille de vos vrais messages (par exemple 256 octets) et "Add timestamp in payload" activé pour que les subscribers puissent calculer la latence.
  • MQTT Sub Sampler. Même QoS, "Payload includes timestamp" activé, échantillonnage sur "number of received messages" (par exemple 100). Chaque échantillon représente alors un lot de messages et rapporte leur latence.
  • Constant Throughput Timer. Sa cible s'exprime en échantillons par minute. Pour 1 000 messages par seconde sur l'ensemble des publishers, indiquez 60 000 et choisissez "all active threads in current thread group". Placez-le en enfant du Pub sampler pour qu'il ne cadence que la publication.

${__threadNum} est le numéro du thread dans son propre groupe : le publisher 17 et le subscriber 17 partagent donc testmqtt/jmeter/17/data. Vérifiez le motif avec le topic matcher si vous passez à des abonnements avec wildcards.

Lancer sans GUI et générer le rapport

Le mode GUI fausse les résultats : l'affichage des listeners consomme du CPU sur le générateur de charge. Lancez en mode non GUI, écrivez les échantillons bruts dans un fichier .jtl et laissez JMeter générer son tableau de bord HTML à la fin :

Exécuter le plan en ligne de commande
export MQTT_USER=username MQTT_PASS=password
HEAP="-Xms1g -Xmx4g" apache-jmeter-5.6.3/bin/jmeter -n \
  -t mqtt-load.jmx \
  -Jhost=broker.connectmq.com -Jport=1883 \
  -Juser="$MQTT_USER" -Jpass="$MQTT_PASS" \
  -Jthreads=200 -Jrate=60000 \
  -l results.jtl -e -o report/

-n active le mode non GUI, -l désigne le fichier de résultats, -e -o génère le tableau de bord dans un dossier vide. Le script de démarrage jmeter lit la variable HEAP ; augmentez-la avec le nombre de threads, car chaque thread maintient un client MQTT complet.

Listeners : lesquels garder, lesquels désactiver

ListenerÀ utiliser pourPendant la charge ?
View Results TreeDéboguer un thread, vérifier les payloadsNon — désactivez-le
Summary Report / Aggregate ReportComptes rapides par sampler, % d'erreurs, throughputSeulement en essai à blanc dans la GUI
Fichier .jtl + tableau de bord HTML (-e -o)Rapport final : percentiles, throughput dans le tempsOui
Backend Listener (InfluxDB)Graphiques en direct dans Grafana pour les longs testsOui, si vous avez besoin de données en direct

Le tableau de bord HTML regroupe les résultats par label de sampler : donnez-leur des noms clairs ("Pub QoS1 256B", "Sub batch 100"), ce sont les titres de votre rapport.

Ce que signifient les chiffres

JMeter affiche un "response time" pour chaque échantillon, mais chaque sampler MQTT mesure autre chose :

SamplerLe temps écoulé correspond àÀ surveiller
MQTT ConnectDe CONNECT à CONNACK (handshake TLS compris)Erreurs et connexions lentes pendant la montée en charge
MQTT Pub SamplerLe temps de remise du message ; en QoS 1/2, il inclut l'attente de l'acquittement du brokerUn temps qui augmente = back-pressure du broker ou du réseau
MQTT Sub SamplerLa fenêtre d'échantillonnage configurée, pas la latence de livraisonMessages reçus par échantillon et latence calculée à partir des timestamps

Les deux chiffres essentiels sont le throughput de publication (échantillons Pub par seconde, dans le tableau de bord) et la latence de bout en bout (calcul des timestamps du Sub sampler). Si les messages reçus prennent du retard sur les messages envoyés, quelque chose est perdu ou mis en file ; relancez en QoS 1 pour distinguer un problème de capacité d'une perte en QoS 0. Une analyse plus poussée des percentiles et des faux goulets d'étranglement se trouve dans interpréter les résultats de benchmark MQTT.

Des erreurs de connexion qui apparaissent pile à un nombre rond de threads signalent généralement une limite du système d'exploitation sur le générateur de charge ou une limite de connexions sur le broker — voir too many connections et retrouvez le reason code avec l'outil des reason codes MQTT.

Faire monter en charge le générateur

Chaque thread JMeter est un thread Java avec son propre client MQTT : JMeter est donc plus lourd par connexion que les outils basés sur Erlang ou Go. Limites pratiques :

  • Augmentez ulimit -n sur le générateur de charge et donnez assez de heap à JMeter.
  • Surveillez le CPU du générateur. Au-delà de 80 % environ, vos mesures décrivent JMeter, pas le broker.
  • Pour plus de connexions, utilisez le mode distribué de JMeter (-R host1,host2) afin que plusieurs machines exécutent le même plan, ou confiez le test de connexions pur à emqtt-bench et gardez JMeter pour les tests de scénarios.
  • Les versions 2.x du plugin ajoutent des samplers de connexion/déconnexion par lots qui ouvrent plusieurs connexions par thread ; consultez les notes de version si vous devez réduire le nombre de threads.

Une démarche JMeter reproductible

  1. Vérifiez une connexion à la main dans le client en ligne.
  2. Lancez le plan dans la GUI avec 2 threads et View Results Tree activé ; vérifiez que tous les samplers réussissent.
  3. Désactivez View Results Tree, enregistrez et lancez sans GUI à 10 %, 50 %, 100 % et 150 % du pic attendu.
  4. Conservez les .jtl et tableaux de bord de chaque exécution avec les métriques CPU, mémoire et connexions du broker.
  5. Versionnez le .jmx dans votre dépôt et relancez-le après chaque mise à jour du broker.

Suivre en direct le trafic de votre test JMeter

JMeter n'est pas le générateur de charge MQTT le plus léger, mais il est pratique quand votre équipe le connaît déjà : plans paramétrés, timers pour des débits de messages précis et rapport HTML prêt à l'emploi. Gardez des samplers simples, lancez sans GUI et lisez le temps de chaque sampler pour ce qu'il mesure vraiment.

Questions fréquentes

JMeter prend-il en charge MQTT nativement ?

Non. JMeter n'a pas de sampler MQTT intégré. Il faut ajouter un plugin comme emqx/mqtt-jmeter (anciennement XMeter), qui fournit les samplers Connect, Pub, Sub et DisConnect. Copiez son jar dans lib/ext et redémarrez JMeter.

JMeter peut-il tester MQTT 5 ?

Le plugin emqx/mqtt-jmeter documente MQTT 3.1 et 3.1.1. Si votre test dépend de fonctions MQTT 5 comme les reason codes, les user properties ou le session expiry, utilisez un outil compatible MQTT 5 comme emqtt-bench ou k6 avec xk6-mqtt.

Combien de connexions MQTT une machine JMeter peut-elle ouvrir ?

Cela dépend du heap, du CPU et des limites du système, car chaque thread JMeter garde une connexion MQTT. Augmentez le heap et ulimit -n, lancez sans GUI et passez au mode distribué ou à un outil plus léger comme emqtt-bench pour des dizaines de milliers de connexions.