Broker-Tests

MQTT-Lasttests mit JMeter: Plugin, Thread Groups und Ergebnisse

MQTT-Broker mit Apache JMeter unter Last testen: MQTT-Plugin installieren, Publisher- und Subscriber-Thread-Groups bauen, headless ausführen, Ergebnisse lesen.

Aktualisiert · 9 Min. Lesezeit

MQTT-Lasttests mit JMeter: Plugin, Thread Groups und Ergebnisse

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:

SamplerWas er tut
MQTT ConnectÖffnet eine Verbindung (TCP, SSL, WS oder WSS) und hält sie für den Thread
MQTT Pub SamplerPublisht auf ein Topic mit gewähltem QoS, Retain-Flag und Payload
MQTT Sub SamplerSubscribt und sampelt empfangene Nachrichten über ein Zeitfenster oder eine Nachrichtenanzahl
MQTT DisConnectSchließ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:

JMeter 5.6.3 und das MQTT-Plugin installieren
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 bauen

Nach 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:

mqtt-load.jmx — Baum des Testplans
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 HOST als ${__P(host,broker.connectmq.com)}, PORT als ${__P(port,1883)} usw. __P liest eine Property, die per -J auf der Kommandozeile übergeben wird, und fällt sonst auf den Standardwert zurück — so dient eine .jmx-Datei allen Umgebungen.
  • MQTT Connect. Server ${HOST} (ohne tcp://-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:

Den Plan von der Kommandozeile starten
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

ListenerWofürWährend der Last?
View Results TreeEinen Thread debuggen, Payloads prüfenNein — deaktivieren
Summary Report / Aggregate ReportSchnelle Zahlen pro Sampler, Fehlerquote, DurchsatzNur bei GUI-Probeläufen
.jtl-Datei + HTML-Dashboard (-e -o)Abschlussreport: Perzentile, Durchsatz über die ZeitJa
Backend Listener (InfluxDB)Live-Graphen in Grafana bei langen LäufenJa, 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:

SamplerDie verstrichene Zeit bedeutetWorauf achten
MQTT ConnectCONNECT bis CONNACK (inklusive TLS-Handshake)Fehler und langsame Verbindungen im Ramp-up
MQTT Pub SamplerZeit bis zur Übergabe der Nachricht; bei QoS 1/2 inklusive Warten auf die Bestätigung des BrokersSteigende Zeit = Back-Pressure von Broker oder Netzwerk
MQTT Sub SamplerDas konfigurierte Sampling-Fenster, nicht die ZustelllatenzEmpfangene 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 -n auf 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

  1. Prüfe eine Verbindung von Hand im Online-Client.
  2. Führe den Plan in der GUI mit 2 Threads und aktiviertem View Results Tree aus; alle Sampler müssen erfolgreich sein.
  3. Deaktiviere View Results Tree, speichere und laufe headless mit 10 %, 50 %, 100 % und 150 % der erwarteten Spitzenlast.
  4. Bewahre .jtl-Dateien und Dashboards jedes Laufs zusammen mit CPU-, Speicher- und Verbindungsmetriken des Brokers auf.
  5. 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.