Das MQTT-Keep-Alive-Intervall ist die Anzahl an Sekunden, die ein Client verspricht, nie länger still zu bleiben, und es ist das wichtigste Werkzeug eines Brokers, um tote Verbindungen zu erkennen. In diesem Leitfaden erfahren Sie genau, wie PINGREQ, PINGRESP und die 1,5-fach-Timeout-Regel funktionieren, wie Keep Alive mit NAT-Routern, Mobilfunkverbindungen und Akkulaufzeit zusammenspielt und mit welchen Werten Sie für Ihre Geräte beginnen sollten.
Was das MQTT-Keep-Alive-Intervall tatsächlich bewirkt
Wenn ein Client CONNECT sendet, enthält es ein zwei Byte langes Feld Keep Alive in Sekunden. Der Wert ist ein Vertrag: „Ich sende dir in diesem Zeitraum mindestens einmal irgendein Control-Paket.“ Jedes Paket zählt, ob PUBLISH, SUBSCRIBE oder PUBACK. Erst wenn der Client nichts anderes zu senden hat, greift er auf ein winziges PINGREQ-Paket zurück, und der Broker antwortet mit PINGRESP.
Keep Alive gibt es, weil TCP selbst schlecht darin ist, tote Gegenstellen zu bemerken. Verliert ein Gerät den Strom oder fällt sein Mobilfunkmodem aus dem Netz, wird nie ein FIN- oder RST-Paket gesendet. Der Socket des Brokers bleibt aus dessen Sicht für immer „offen“, und jeder Subscriber, der auf das Last Will and Testament des Geräts wartet, wartet ebenfalls ewig. Keep Alive gibt beiden Seiten eine Frist.
Die 1,5-fach-Timeout-Regel
Die MQTT-Spezifikation besagt: Empfängt der Broker innerhalb des Anderthalbfachen des Keep-Alive-Intervalls nichts von einem Client, muss er die Netzwerkverbindung schließen, als wäre sie ausgefallen. Das bedeutet:
| Keep Alive | Broker gibt auf nach | Typischer Einsatz |
|---|---|---|
| 15 s | 22,5 s | Interaktive Dashboards, schnelles Failover |
| 30 s | 45 s | Netzbetriebene Geräte in unzuverlässigem WLAN |
| 60 s | 90 s | Sinnvoller Standard für die meisten Geräte |
| 120 s | 180 s | Mobilfunkgeräte mit Blick auf den Datenverbrauch |
| 300 s | 450 s | Selten kommunizierende Gateways auf stabilen Verbindungen |
| 0 | Nie | Keep Alive deaktiviert (in Produktion vermeiden) |
Auch der Client hat seinen Teil der Abmachung. Sendet er PINGREQ und erhält nicht innerhalb einer „angemessenen Zeit“ ein PINGRESP (die meisten Bibliotheken verwenden den Keep-Alive-Wert oder einen festen Timeout), sollte er die Verbindung als unterbrochen betrachten und sich neu verbinden. So entdeckt ein Client einen halboffenen Socket auf seiner Seite.
Was passiert, wenn der Timeout greift
Schließt der Broker eine Verbindung wegen Keep Alive, behandelt er dies als abnormale Trennung. Praktische Folgen:
- Die Will-Nachricht des Clients wird veröffentlicht (nach dem Will Delay, falls Sie in MQTT 5 einen gesetzt haben; siehe MQTT Will Delay Interval).
- Hatte der Client eine persistente Session, behält der Broker dessen Subscriptions und beginnt, QoS-1- und QoS-2-Nachrichten für ihn zwischenzuspeichern.
- Online-Status-Topics und Dashboards wechseln auf „offline“.
Keep Alive bestimmt also direkt, wie schnell Ihr System erfährt, dass etwas schiefgelaufen ist.
Einen MQTT-Keep-Alive-Wert wählen
Es gibt keinen allgemeingültig richtigen Wert. Sie wägen Erkennungsgeschwindigkeit gegen Datenverkehr und Energie ab.
Erkennungsgeschwindigkeit
Ein kürzeres Intervall bedeutet, dass Broker und Subscriber schneller von Ausfällen erfahren. Muss ein Bediener-Dashboard in der Leitwarte eine Maschine oder ein SPS-Gateway innerhalb einer halben Minute als offline anzeigen, erfüllt ein Keep Alive von 60 Sekunden (90 Sekunden Erkennungszeit) diese Anforderung nicht, 15 oder 20 Sekunden dagegen schon.
Idle-Timeouts von NAT und Firewall
Das ist die Falle, in die die meisten Teams tappen. Heimrouter, Unternehmens-Firewalls, Cloud-Load-Balancer und vor allem NAT-Gateways von Mobilfunkanbietern verwerfen TCP-Zuordnungen, die eine Weile inaktiv waren. Ist die Zuordnung weg, geht das nächste Paket des Clients ins Leere, und der Broker bemerkt es erst an der 1,5-fach-Frist. Ist Ihr Keep Alive länger als der kürzeste NAT-Idle-Timeout auf dem Pfad, erleben Sie rätselhafte Trennungen alle paar Minuten. Die NAT-Timeouts der Provider schwanken stark und sind nicht immer dokumentiert. Auf Mobilfunkverbindungen ist es daher sicherer, deutlich unter einigen Minuten zu bleiben.
Akku und Datenverbrauch
Jeder Austausch von PINGREQ und PINGRESP umfasst nur 2 Byte MQTT pro Richtung plus TCP/IP-Overhead (und TLS-Record-Overhead). Im WLAN ist das vernachlässigbar. Bei einem akkubetriebenen Mobilfunkgerät entstehen die Kosten vor allem durch das Aufwecken des Funkmoduls, nicht durch Bytes: Jeder Ping kann das Modem sekundenlang in einem stromhungrigen Zustand halten. Überlegen Sie bei solchen Geräten, ob Sie überhaupt eine dauerhafte Verbindung brauchen oder ob Aufwachen, Veröffentlichen und Trennen mit persistenter Session besser ist.
Ein praktischer Ausgangspunkt
- Netzbetriebene Geräte in WLAN oder Ethernet, etwa Edge-Gateways an der Fertigungslinie: 60 Sekunden.
- Dashboards und Browser-Clients über WebSocket: 30 Sekunden.
- Mobilfunk-Gateways: 60 bis 120 Sekunden, dann verkürzen, wenn Sie unerklärliche Abbrüche sehen.
- Backend-Dienste in derselben Cloud-Region: 30 bis 60 Sekunden.
- Verwenden Sie in der Produktion nie 0; damit entfällt die Erkennung toter Verbindungen vollständig.
Das Keep-Alive-Intervall in gängigen Clients einstellen
Sie können all das gegen den öffentlichen MQTT-Broker unter broker.connectmq.com ausprobieren. Verwenden Sie eine eindeutige Client ID und ein eindeutiges Topic-Präfix und denken Sie daran, dass der öffentliche Bereich für alle lesbar ist. Er eignet sich für Tests und Prototypen, nicht für Produktionsdaten.
mosquitto_sub und mosquitto_pub
# Mit 30 Sekunden Keep Alive und Debug-Ausgabe abonnieren, um PINGREQ/PINGRESP zu sehen
mosquitto_sub -h broker.connectmq.com -p 1883 -i ka-demo-7f3a \
-k 30 -d -t 'connectmq/demo/7f3a/#'
Mit -d sehen Sie alle 30 Sekunden, solange auf dem Topic nichts los ist, Zeilen wie Client ka-demo-7f3a sending PINGREQ und received PINGRESP.
Python (paho-mqtt 2.x)
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, reason_code, properties):
print("Connected:", reason_code)
client.subscribe("connectmq/demo/7f3a/#", qos=1)
def on_disconnect(client, userdata, flags, reason_code, properties):
print("Disconnected:", reason_code)
client = mqtt.Client(
mqtt.CallbackAPIVersion.VERSION2,
client_id="ka-python-7f3a",
protocol=mqtt.MQTTv5,
)
client.on_connect = on_connect
client.on_disconnect = on_disconnect
# keepalive ist das dritte Argument, in Sekunden
client.connect("broker.connectmq.com", 1883, keepalive=60)
client.loop_forever()
paho sendet PINGREQ automatisch aus seiner Netzwerkschleife. Blockieren Sie die Schleife (zum Beispiel mit einem langen time.sleep in einem Callback), hören die Pings auf, und der Broker trennt Sie nach dem 1,5-Fachen des Intervalls.
Node.js (MQTT.js v5)
const mqtt = require("mqtt");
const client = mqtt.connect("mqtts://broker.connectmq.com:8883", {
clientId: "ka-node-7f3a",
protocolVersion: 5,
keepalive: 45, // Sekunden
reconnectPeriod: 5000, // ms zwischen Reconnect-Versuchen
});
client.on("connect", () => console.log("connected"));
client.on("close", () => console.log("connection closed"));
client.on("error", (err) => console.error(err.message));
ESP32 (PubSubClient)
PubSubClient verwendet standardmäßig 15 Sekunden. Ändern Sie den Wert vor dem Aufruf von connect() mit client.setKeepAlive(60); und stellen Sie sicher, dass client.loop() in Ihrem Sketch häufig läuft, denn Pings werden nur innerhalb von loop() gesendet. Lange delay()-Aufrufe sind der häufigste Grund, warum ESP32-Boards in regelmäßigen Abständen die Verbindung verlieren. Ein gut strukturierter ESP32-Sketch verwendet eine nicht blockierende Schleife mit millis()-Timern, um das zu vermeiden.
Server Keep Alive in MQTT 5
MQTT 5 erlaubt dem Broker, die Anfrage des Clients zu überschreiben. Enthält das CONNACK eine Property Server Keep Alive, muss der Client diesen Wert statt seines eigenen verwenden. Broker tun das, um auf einer geteilten Plattform ein Mindest- oder Höchstintervall durchzusetzen. Die meisten Bibliotheken übernehmen den Wert stillschweigend. Bemerken Sie Pings in einer anderen Rate als konfiguriert, protokollieren Sie daher die CONNACK-Properties. In paho können Sie properties in on_connect ausgeben; MQTT.js stellt sie im connack-Paket bereit, das an das connect-Event übergeben wird.
Keep-Alive-Probleme beheben
Nutzen Sie diese Checkliste, wenn Clients in verdächtig regelmäßigen Abständen die Verbindung verlieren:
- Messen Sie den Abstand. Treten Trennungen etwa beim 1,5-Fachen Ihres Keep Alive nach der letzten Aktivität auf, sendet der Client keine Pings. Suchen Sie nach einer blockierten Netzwerkschleife.
- Prüfen Sie auf einen festen Leerlaufabbruch. Treten Abbrüche unabhängig vom Keep Alive nach einer konstanten Anzahl von Minuten auf, läuft ein NAT- oder Firewall-Timeout ab. Senken Sie das Intervall unter diesen Wert.
- Suchen Sie nach doppelten Client IDs. Zwei Clients mit derselben ID werfen sich gegenseitig hinaus, was wie ein Keep-Alive-Problem aussieht, aber keines ist. Siehe Best Practices für die MQTT Client ID.
- Achten Sie auf Single-Thread-Callbacks. Aufwendige Verarbeitung in
on_messageverzögert PINGREQ. Verlagern Sie die Verarbeitung in einen Worker-Thread oder eine Queue. - Prüfen Sie, ob TLS-Handshakes abgeschlossen werden. Auf ressourcenarmen Geräten kann ein langsamer TLS-Reconnect den nächsten Ping über die Frist hinausschieben.
- Aktivieren Sie das Debug-Logging Ihrer Bibliothek und vergleichen Sie die Zeitstempel des Clients mit den Verbindungsereignissen des Brokers.
Auf einem ConnectMQ-Broker können Sie außerdem $SYS/broker/connection/{clientId}/state beobachten, um genau zu sehen, wann der Broker einen Client als verbunden oder getrennt betrachtet. So lässt sich das leicht mit Ihren Geräte-Logs abgleichen. Mit dem browserbasierten MQTT-Client im Portal abonnieren Sie dieses Topic schnell, ohne etwas zu installieren.
Keep Alive, Sessions und Last Will im Zusammenspiel
Keep Alive ist ein Baustein eines größeren Zuverlässigkeitskonzepts. Ein sinnvolles Produktionsmuster sieht so aus:
- Ein Keep Alive, der kurz genug ist, um NAT-Timeouts zuvorzukommen und Ihr Erkennungsziel zu erfüllen.
- Eine retained „online“-Nachricht beim Verbindungsaufbau plus eine retained „offline“-Will-Nachricht. In einem Unified Namespace (UNS) nach ISA-95 liegt dieser Status idealerweise direkt am Knoten der Maschine, etwa unter
acme/werk-stuttgart/montage/linie-1/zelle-3/status, sodass MES und SCADA ihn an derselben Stelle finden wie die Messwerte. - Eine persistente Session, damit QoS-1-Nachrichten, die während des Reconnects des Geräts veröffentlicht werden, nicht verloren gehen.
- Exponentieller Backoff beim Reconnect, damit ein Broker-Neustart nicht zu einem Ansturm aller Clients gleichzeitig führt.
Das MQTT-Tutorial behandelt diese Bausteine von Anfang an, wenn Sie den größeren Zusammenhang möchten.
Starten Sie mit ConnectMQ
ConnectMQ ist ein verwalteter MQTT-Broker, der MQTT 3.1.1 und 5.0 über TCP, TLS, WebSocket und sicheres WebSocket unterstützt. So können Sie jede Keep-Alive-Strategie auf denselben Endpunkten testen, die Sie auch in der Produktion verwenden. Wenn Sie über den öffentlichen MQTT-Broker hinausgehen möchten, erstellen Sie einen kostenlosen Serverless-Broker ohne Kreditkarte, kopieren Sie die generierten Zugangsdaten und verfolgen Sie den Verbindungsstatus live im Portal. Wenn Sie noch Optionen vergleichen, erläutert unser Leitfaden zur Wahl eines Cloud-MQTT-Brokers die Abwägungen.
Häufig gestellte Fragen
Was ist ein guter Standardwert für das MQTT-Keep-Alive-Intervall?
60 Sekunden sind ein guter Standard für die meisten netzbetriebenen Geräte. Verkürzen Sie auf 15 bis 30 Sekunden, wenn Sie Offline-Zustände schneller erkennen müssen oder ein NAT-Gerät auf dem Pfad inaktive Verbindungen früher verwirft.
Setzt jedes MQTT-Paket den Keep-Alive-Timer zurück?
Ja. Jedes Control-Paket, das der Client sendet, einschließlich PUBLISH und PUBACK, zählt als Aktivität. PINGREQ wird nur gesendet, wenn der Client ansonsten für das gesamte Intervall inaktiv war.
Was passiert, wenn ich Keep Alive auf 0 setze?
Keep Alive ist dann deaktiviert, und der Broker schließt eine stille Verbindung nie von sich aus. Tote Geräte können unbegrenzt als verbunden erscheinen, und ihre Will-Nachrichten werden womöglich nie gesendet. Vermeiden Sie 0 daher in der Produktion.
Warum trennt mein Client genau alle paar Minuten die Verbindung?
Ein konstantes Intervall unabhängig von Ihrer Keep-Alive-Einstellung deutet meist auf einen Idle-Timeout von NAT oder Firewall hin. Setzen Sie den Keep Alive unter diesen Timeout, damit Pings die Zuordnung am Leben halten.
Kann der Broker meinen Keep-Alive-Wert ändern?
In MQTT 5 ja. Der Broker kann im CONNACK eine Property Server Keep Alive zurückgeben, und der Client muss diesen Wert statt des angeforderten verwenden.



