Apache JMeter kann einen MQTT-Broker unter Last testen, sobald du ein MQTT-Plugin hinzufügst: Jeder JMeter-Thread wird zu einem MQTT-Client, der sich verbindet, publisht oder subscribt, und Timer, Listener und der HTML-Report von JMeter erledigen den Rest. Wenn dein Team JMeter schon für HTTP nutzt, behältst du so ein Tool, ein Reportformat und einen CI-Job auch für deine MQTT-Tests.
Diese Anleitung installiert das Plugin, baut einen Testplan mit Publishern und Subscribern, führt ihn headless aus und erklärt, was die Zahlen tatsächlich messen.
Das passende MQTT-Plugin
JMeter bringt keinen MQTT-Sampler mit. Die verbreitetste Option ist emqx/mqtt-jmeter (ursprünglich von XMeter veröffentlicht). Es fügt vier Sampler hinzu:
| Sampler | Was er tut |
|---|---|
| MQTT Connect | Öffnet eine Verbindung (TCP, SSL, WS oder WSS) und hält sie für den Thread |
| MQTT Pub Sampler | Publisht auf ein Topic mit gewähltem QoS, Retain-Flag und Payload |
| MQTT Sub Sampler | Subscribt und sampelt empfangene Nachrichten über ein Zeitfenster oder eine Nachrichtenanzahl |
| MQTT DisConnect | Schließt die Verbindung des Threads |
Pub- und Sub-Sampler verwenden die Verbindung, die der Connect-Sampler im selben Thread aufgebaut hat. Existiert noch keine Verbindung, schlagen sie sofort fehl — genau das willst du im Report sehen.
JMeter und Plugin installieren
JMeter braucht eine Java-Runtime (Java 8 oder neuer für JMeter 5.6). Lade JMeter herunter und kopiere das Plugin-Jar von der Release-Seite des Projekts nach lib/ext:
curl -LO https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-5.6.3.tgz
tar xzf apache-jmeter-5.6.3.tgz
# aktuelles Jar von https://github.com/emqx/mqtt-jmeter/releases herunterladen
cp ~/Downloads/mqtt-xmeter-*.jar apache-jmeter-5.6.3/lib/ext/
apache-jmeter-5.6.3/bin/jmeter # GUI starten, um den Plan zu bauenNach dem Neustart erscheinen die vier MQTT-Sampler per Rechtsklick auf eine Thread Group → Add → Sampler. Nutze die GUI nur zum Bauen und Debuggen des Plans; echte Last erzeugst du über die Kommandozeile.
Prüfe vor jeder Last, ob Host, Port und Zugangsdaten mit einem einzelnen Client im Online-MQTT-Client funktionieren. Ein falsches Passwort bei 500 Threads erzeugt 500 identische Fehler und keine Erkenntnis. Die Beispiele nutzen broker.connectmq.com, einen geteilten Endpoint für schnelle Funktionstests; für den eigentlichen Lastlauf richtest du -Jhost und die Zugangsdaten auf deine eigene private Broker-Instanz.
Den Testplan bauen
Ein realistischer Telemetrie-Test hat zwei Gruppen von Clients: Publisher, die Gerätedaten senden, und Subscriber, die sie konsumieren. Dieser Aufbau gibt jedem Publisher ein eigenes Topic und einen eigenen Subscriber (eins zu eins), sodass du das Routing misst und nicht den Fan-out:
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)Die wichtigsten Einstellungen, Sampler für Sampler:
- Variablen. Definiere
HOSTals${__P(host,broker.connectmq.com)},PORTals${__P(port,1883)}usw.__Pliest eine Property, die per-Jauf der Kommandozeile übergeben wird, und fällt sonst auf den Standardwert zurück — so dient eine.jmx-Datei allen Umgebungen. - MQTT Connect. Server
${HOST}(ohnetcp://-Präfix), Port${PORT}, Protokoll TCP (oder SSL mit Port 8883, WSS mit 8084), Benutzername und Passwort aus Properties, Keep Alive wie bei deinen Geräten. Aktiviere das zufällige Client-ID-Suffix — zwei Threads mit derselben Client-ID werfen sich gegenseitig vom Broker. - Once Only Controller. Der Publisher-Thread verbindet sich nur in der ersten Iteration und wiederholt danach den Pub-Sampler. Ohne ihn öffnet jede Iteration eine neue Verbindung, und du testest die Verbindungsrate statt des Durchsatzes.
- MQTT Pub Sampler. QoS 1, Retain aus, Payload-Typ "random string with fixed length" in der Größe deiner echten Nachrichten (zum Beispiel 256 Byte) und "Add timestamp in payload" aktiviert, damit die Subscriber die Latenz berechnen können.
- MQTT Sub Sampler. Gleicher QoS, "Payload includes timestamp" aktiviert, Sampling nach "number of received messages" (zum Beispiel 100). Jedes Sample steht dann für einen Nachrichtenstapel und meldet dessen Latenz.
- Constant Throughput Timer. Das Ziel wird in Samples pro Minute angegeben. Für 1.000 Nachrichten pro Sekunde über alle Publisher setzt du 60.000 und wählst "all active threads in current thread group". Hänge ihn als Kind unter den Pub-Sampler, damit er nur das Publishing taktet.
${__threadNum} ist die Thread-Nummer innerhalb der eigenen Gruppe, also teilen sich Publisher 17 und Subscriber 17 das Topic testmqtt/jmeter/17/data. Prüfe das Muster mit dem Topic Matcher, wenn du auf Wildcard-Subscriptions umstellst.
Headless ausführen und Report erzeugen
Der GUI-Modus verfälscht Ergebnisse: Das Rendern der Listener kostet CPU auf dem Lastgenerator. Laufe im Non-GUI-Modus, schreibe die Rohdaten in eine .jtl-Datei und lass JMeter am Ende sein HTML-Dashboard bauen:
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 ist der Non-GUI-Modus, -l die Ergebnisdatei, -e -o erzeugt das Dashboard in einem leeren Ordner. Die Variable HEAP liest das Startskript jmeter; erhöhe sie mit der Thread-Anzahl, denn jeder Thread hält einen vollständigen MQTT-Client.
Listener: was bleibt, was aus muss
| Listener | Wofür | Während der Last? |
|---|---|---|
| View Results Tree | Einen Thread debuggen, Payloads prüfen | Nein — deaktivieren |
| Summary Report / Aggregate Report | Schnelle Zahlen pro Sampler, Fehlerquote, Durchsatz | Nur bei GUI-Probeläufen |
.jtl-Datei + HTML-Dashboard (-e -o) | Abschlussreport: Perzentile, Durchsatz über die Zeit | Ja |
| Backend Listener (InfluxDB) | Live-Graphen in Grafana bei langen Läufen | Ja, wenn du Live-Daten brauchst |
Das HTML-Dashboard gruppiert nach Sampler-Label, also vergib klare Namen ("Pub QoS1 256B", "Sub batch 100") — die Labels sind die Überschriften deines Reports.
Was die Zahlen bedeuten
JMeter meldet für jedes Sample eine "Response Time", aber jeder MQTT-Sampler misst etwas anderes:
| Sampler | Die verstrichene Zeit bedeutet | Worauf achten |
|---|---|---|
| MQTT Connect | CONNECT bis CONNACK (inklusive TLS-Handshake) | Fehler und langsame Verbindungen im Ramp-up |
| MQTT Pub Sampler | Zeit bis zur Übergabe der Nachricht; bei QoS 1/2 inklusive Warten auf die Bestätigung des Brokers | Steigende Zeit = Back-Pressure von Broker oder Netzwerk |
| MQTT Sub Sampler | Das konfigurierte Sampling-Fenster, nicht die Zustelllatenz | Empfangene Nachrichten pro Sample und die aus Timestamps berechnete Latenz |
Die zwei wichtigsten Kennzahlen sind der Publish-Durchsatz (Pub-Samples pro Sekunde, aus dem Dashboard) und die End-to-End-Latenz (aus der Timestamp-Berechnung des Sub-Samplers). Bleiben empfangene Nachrichten hinter den gesendeten zurück, wird etwas verworfen oder gepuffert; wiederhole den Lauf mit QoS 1, um Kapazitätsprobleme von QoS-0-Verlusten zu trennen. Eine ausführlichere Erklärung zu Perzentilen und falschen Engpässen findest du unter MQTT-Benchmark-Ergebnisse interpretieren.
Verbindungsfehler, die genau bei einer runden Thread-Zahl auftreten, deuten meist auf ein Betriebssystem-Limit am Lastgenerator oder ein Verbindungslimit am Broker hin — siehe too many connections und schlage den Reason Code im MQTT-Reason-Code-Tool nach.
Den Lastgenerator skalieren
Jeder JMeter-Thread ist ein Java-Thread mit eigenem MQTT-Client, daher ist JMeter pro Verbindung schwerer als Tools auf Erlang- oder Go-Basis. Praktische Grenzen:
- Erhöhe
ulimit -nauf dem Lastgenerator und gib JMeter genug Heap. - Beobachte die CPU des Generators. Ab etwa 80 % beschreiben deine Messungen JMeter, nicht den Broker.
- Für mehr Verbindungen nutzt du den verteilten Modus von JMeter (
-R host1,host2), damit mehrere Maschinen denselben Plan ausführen, oder du verlagerst den reinen Verbindungstest zu emqtt-bench und nutzt JMeter für Szenariotests. - Die 2.x-Releases des Plugins bringen Batch-Connect/Disconnect-Sampler, die mehrere Verbindungen pro Thread öffnen; sieh in die Release Notes, wenn du die Thread-Zahl senken musst.
Ein wiederholbarer JMeter-Ablauf
- Prüfe eine Verbindung von Hand im Online-Client.
- Führe den Plan in der GUI mit 2 Threads und aktiviertem View Results Tree aus; alle Sampler müssen erfolgreich sein.
- Deaktiviere View Results Tree, speichere und laufe headless mit 10 %, 50 %, 100 % und 150 % der erwarteten Spitzenlast.
- Bewahre
.jtl-Dateien und Dashboards jedes Laufs zusammen mit CPU-, Speicher- und Verbindungsmetriken des Brokers auf. - Committe die
.jmx-Datei ins Repository und führe sie nach jedem Broker-Upgrade erneut aus.
Den Traffic deines JMeter-Tests live ansehen
JMeter ist nicht der leichteste MQTT-Lastgenerator, aber ein praktischer, wenn dein Team ihn schon kennt: parametrisierte Pläne, Timer für exakte Nachrichtenraten und ein fertiger HTML-Report. Halte die Sampler einfach, laufe headless und lies die Zeit jedes Samplers als das, was sie wirklich misst.
Häufig gestellte Fragen
Unterstützt JMeter MQTT von Haus aus?
Nein. JMeter hat keinen eingebauten MQTT-Sampler. Du brauchst ein Plugin wie emqx/mqtt-jmeter (früher XMeter), das die Sampler Connect, Pub, Sub und DisConnect mitbringt. Kopiere das Jar nach lib/ext und starte JMeter neu.
Kann JMeter MQTT 5 testen?
Das Plugin emqx/mqtt-jmeter dokumentiert MQTT 3.1 und 3.1.1. Hängt dein Test von MQTT-5-Features wie Reason Codes, User Properties oder Session Expiry ab, nimm ein Tool mit MQTT-5-Support wie emqtt-bench oder k6 mit xk6-mqtt.
Wie viele MQTT-Verbindungen schafft ein JMeter-Rechner?
Das hängt von Heap, CPU und Betriebssystem-Limits ab, denn jeder JMeter-Thread hält eine MQTT-Verbindung. Erhöhe Heap und ulimit -n, laufe headless und nutze den verteilten Modus oder ein leichteres Tool wie emqtt-bench, wenn du Zehntausende Verbindungen brauchst.



