Das MQTT Session Expiry Interval teilt dem Broker mit, wie lange er die Session eines Clients nach dem Trennen aufbewahren soll. Zusammen mit dem Clean-Start-Flag ersetzt es das Alles-oder-nichts-Flag Clean Session aus MQTT 3.1.1. In diesem Artikel erfahren Sie, wie beide Einstellungen zusammenwirken, wie sich das Intervall beim Trennen noch ändern lässt und wie Sie sinnvolle Werte für Sensoren, Gateways und Backend-Dienste wählen.
Warum MQTT 5 das Clean-Session-Flag ersetzt hat
In MQTT 3.1.1 erledigte cleanSession zwei Aufgaben mit einem Bit. Der Wert false bedeutete „meine alte Session fortsetzen und diese hier für immer behalten“. Es gab keine Möglichkeit zu sagen: „Setze meine Session fort, aber vergiss sie, wenn ich länger als eine Stunde weg bin.“ Broker behalfen sich mit serverseitigen Ablaufeinstellungen, wodurch sich das Verhalten von Broker zu Broker unterschied und sich verwaiste Sessions anhäuften.
MQTT 5 trennt die beiden Anliegen:
- Clean Start (ein CONNECT-Flag) beantwortet: Soll der Broker eine bestehende Session jetzt sofort verwerfen?
- Session Expiry Interval (eine CONNECT-Property in Sekunden) beantwortet: Wie lange soll die Session nach dem Schließen der Netzwerkverbindung weiterleben?
Das Design ist in der OASIS-Spezifikation zu MQTT 5.0 beschrieben und gehört zu den praktischsten Verbesserungen, die wir in unserer Übersicht der MQTT-5-Features behandeln.
Wie Clean Start und Session Expiry zusammenwirken
| Clean Start | Session Expiry Interval | Verhalten | Entsprechung in 3.1.1 |
|---|---|---|---|
| true | 0 (oder fehlt) | Neue Session, wird beim Trennen gelöscht | cleanSession = true |
| false | 0 (oder fehlt) | Bestehende Session fortsetzen, falls vorhanden; wird beim Trennen gelöscht | Keine direkte Entsprechung |
| true | > 0 | Alte Session verwerfen, neue anlegen, die das Trennen N Sekunden überdauert | Keine direkte Entsprechung |
| false | > 0 | Fortsetzen, falls vorhanden; überdauert das Trennen N Sekunden | cleanSession = false (mit Timeout) |
| false | 0xFFFFFFFF | Fortsetzen, falls vorhanden; läuft nie ab | cleanSession = false |
In der Praxis kommt es auf einige Details an:
- Der Timer startet, wenn die Netzwerkverbindung geschlossen wird, nicht beim letzten Publish des Clients.
- Verbindet sich der Client vor Ablauf des Timers neu, wird die Session fortgesetzt und der Timer gestoppt.
- Ist das Intervall abgelaufen, löscht der Broker die Subscriptions und alle gepufferten Nachrichten.
- Läuft die Session ab, wird die Will Message spätestens zu diesem Zeitpunkt gesendet, auch wenn das Will Delay Interval länger ist.
Das Intervall beim Trennen ändern
In MQTT 5 kann ein Client den Ablaufwert in seinem DISCONNECT-Paket aktualisieren. Ein Gerät, das in eine geplante Wartung geht, kann beim Abmelden sagen „behalte meine Session einen Tag lang“, während es im Normalbetrieb mit einem kürzeren Wert läuft. Es gibt eine Einschränkung: Hat sich der Client mit einem Ablaufwert von 0 verbunden, darf er beim Trennen keinen Wert ungleich null setzen; der Broker wertet das als Protokollfehler.
Der Broker kann Ihren Wert überschreiben
Ein Broker darf sich weigern, Sessions so lange aufzubewahren, wie Sie es anfordern. In diesem Fall liefert er im CONNACK eine Session-Expiry-Interval-Property zurück, und dieser Wert gilt. Protokollieren Sie während der Entwicklung immer die CONNACK-Properties, damit Sie den tatsächlichen Wert kennen. Auf dem kostenlosen öffentlichen MQTT-Broker unter broker.connectmq.com ist der Session-Ablauf auf 30 Minuten begrenzt.
Das passende MQTT Session Expiry Interval wählen
Stellen Sie sich zwei Fragen: Wie lange kann dieser Client realistischerweise offline sein, und wie alt darf eine gepufferte Nachricht werden, bevor sie nutzlos ist?
| Client-Typ | Empfohlener Ablauf | Begründung |
|---|---|---|
| Live-Dashboard, Browser-Tab | 0 | Nur aktuelle Daten zählen; Retained Messages füllen die Anzeige beim Verbinden |
| Netzbetriebener Sensor, der nur veröffentlicht | 0 bis 300 s | Wenig Session-Zustand; ein kurzer Ablauf räumt schnell auf |
| Gerät, das Befehle empfängt (etwa ein Edge-Gateway an einer SPS) | 1 bis 24 h | Befehle sollen WLAN-Abbrüche, kurze Ausfälle und Schichtwechsel-Neustarts überstehen |
| Schlafendes Batteriegerät, das stündlich aufwacht | Etwas länger als das Weckintervall | Die Session muss die Schlafphase überdauern |
| Backend-Worker, der Alarme verarbeitet (etwa ein MES-Konnektor) | Stunden, abgestimmt auf Ihre Wiederherstellungszeit | Verpasste Alarme müssen nach Redeployments verarbeitet werden |
| Außer Betrieb genommener oder Test-Client | 0 | Keine verwaisten Sessions hinterlassen |
Kombinieren Sie lange Ablaufintervalle bei zeitkritischen Veröffentlichungen mit der MQTT-5-Property Message Expiry Interval. Ein „Pumpe starten“-Befehl, der sechs Stunden in einer Warteschlange liegt, kann gefährlicher sein als einer, der nie zugestellt wird. In der Fertigung gilt das besonders für Befehle, die über einen Unified Namespace (UNS) an eine Anlage gehen, etwa an acme/werk-stuttgart/montage/linie-1/zelle-3/cmd: Ein Rezeptwechsel, der erst nach Schichtende ankommt, richtet mehr Schaden an als ein verworfener.
Ein durchgerechnetes Beispiel: schlafender Sensor mit Befehlen
Stellen Sie sich einen Batteriesensor vor, der alle 15 Minuten aufwacht, einen Messwert veröffentlicht, nach Konfigurationsbefehlen sieht und wieder schläft. Läge sein Session-Ablauf bei 0, würde jeder Befehl, der während des Schlafs gesendet wird, verworfen, weil es keine Session gäbe, in der er gepuffert werden könnte. Wäre der Ablauf unendlich, hinterließe ein im Feld ausgefallener Sensor eine Session, die weiter Befehle sammelt, die niemand mehr liest. Ein Wert von etwa 20 bis 30 Minuten deckt ein verpasstes Aufwachen plus etwas Netzwerk-Jitter ab, und die Session verschwindet von selbst, sobald das Gerät wirklich weg ist. Senden Sie Befehle mit QoS 1 und einer Message Expiry von einigen Stunden, dann erhält das Gerät beim nächsten Verbinden alles, was noch relevant ist.
Session Expiry im Code setzen
Alle Beispiele verwenden ein eindeutiges Demo-Präfix auf dem kostenlosen öffentlichen MQTT-Broker. Ersetzen Sie s4e8 durch eine eigene Zufallszeichenfolge; der öffentliche MQTT-Broker ist für Tests gedacht und für alle sichtbar.
mosquitto_sub
# Session fortsetzen (oder anlegen), die 10 Minuten nach dem Trennen überdauert
mosquitto_sub -h broker.connectmq.com -p 1883 -V mqttv5 \
-i expiry-demo-s4e8 -c -x 600 -q 1 -v -d \
-t 'connectmq/demo/s4e8/commands/#'
-c setzt Clean Start auf false, und -x 600 setzt das Session Expiry Interval. Das Flag -d gibt das CONNACK aus, sodass Sie sehen, ob der Broker den Wert gewährt hat.
Python (paho-mqtt 2.x)
import paho.mqtt.client as mqtt
from paho.mqtt.properties import Properties
from paho.mqtt.packettypes import PacketTypes
def on_connect(client, userdata, flags, reason_code, properties):
granted = getattr(properties, "SessionExpiryInterval", None)
print("Connected:", reason_code,
"| session present:", flags.session_present,
"| broker override:", granted)
if not flags.session_present:
client.subscribe("connectmq/demo/s4e8/commands/#", qos=1)
def on_message(client, userdata, msg):
print("Command:", msg.topic, msg.payload.decode())
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
client_id="expiry-py-s4e8",
protocol=mqtt.MQTTv5)
client.on_connect = on_connect
client.on_message = on_message
connect_props = Properties(PacketTypes.CONNECT)
connect_props.SessionExpiryInterval = 600
client.connect("broker.connectmq.com", 1883, keepalive=60,
clean_start=False, properties=connect_props)
client.loop_start()
try:
input("Press Enter to disconnect with a 30 minute expiry...\n")
finally:
bye = Properties(PacketTypes.DISCONNECT)
bye.SessionExpiryInterval = 1800
client.disconnect(properties=bye)
client.loop_stop()
Node.js (MQTT.js v5)
const mqtt = require("mqtt");
const client = mqtt.connect("mqtts://broker.connectmq.com:8883", {
clientId: "expiry-node-s4e8",
protocolVersion: 5,
clean: false, // Clean Start = false
properties: { sessionExpiryInterval: 600 },
});
client.on("connect", (connack) => {
console.log("session present:", connack.sessionPresent,
"props:", connack.properties);
if (!connack.sessionPresent) {
client.subscribe("connectmq/demo/s4e8/commands/#", { qos: 1 });
}
});
client.on("message", (topic, payload) => {
console.log(topic, payload.toString());
});
Häufige Fehler und wie Sie sie erkennen
- Clean Start false, Ablauf 0. Entwickler portieren 3.1.1-Code, setzen
clean: falseund vergessen die Expiry-Property. In MQTT 5 wird diese Session in dem Moment gelöscht, in dem die Verbindung abbricht, es wird also nie etwas gepuffert. Wenn gepufferte Nachrichten nie ankommen, prüfen Sie das zuerst. - Unendlicher Ablauf bei Test-Clients. Jedes Wegwerfskript mit eindeutiger ID und
0xFFFFFFFFhinterlässt eine Session. Verwenden Sie für Experimente 0, sofern Sie nicht gerade Sessions testen. - Session Present ignorieren. Wurde der Broker neu gestartet oder ist die Session abgelaufen, ist Session Present 0 und Ihre Subscriptions sind weg. Abonnieren Sie in diesem Fall immer erneut.
- Dauerhaftigkeit über Broker-Neustarts annehmen. Session Expiry beschreibt, wie lange eine Session leben darf, keine Speichergarantie. ConnectMQ hält den Session-Zustand im Arbeitsspeicher: Er übersteht Client-Trennungen für das gewährte Intervall, wird aber gelöscht, wenn der Broker selbst neu startet.
- Wechselnde Client-IDs. Der Ablauf ist an die Client-ID gebunden. Eine neue ID ist eine neue Session; siehe Best Practices für die MQTT Client-ID.
Wie das ins Gesamtbild passt
Session Expiry ist der MQTT-5-Weg, Persistent Sessions sicher zu betreiben: Sie erhalten Offline-Pufferung, wo Sie sie brauchen, und automatisches Aufräumen, wo nicht. Wenn Sie die Bausteine des Protokolls noch kennenlernen, ist das vollständige MQTT-Tutorial eine gute Ergänzung.
MQTT-5-Sessions mit ConnectMQ nutzen
ConnectMQ ist ein verwalteter MQTT-Broker mit vollständiger MQTT-5.0-Unterstützung, einschließlich Session Expiry, Message Expiry, Topic Aliases und Reason Codes. Sie können Kombinationen aus Clean Start und Ablaufwert mit dem MQTT-Client im Browser des Portals oder mit eigenem Code testen und dieselben Einstellungen anschließend in die Produktion übernehmen. Starten Sie mit dem kostenlosen Serverless-Tarif, ohne Kreditkarte, und verbinden Sie sich mit Ihren generierten Zugangsdaten YOUR_USERNAME, YOUR_PASSWORD und YOUR_CLIENT_ID.
Häufig gestellte Fragen
Was ist der Standardwert des MQTT Session Expiry Interval?
Fehlt die Property, beträgt das Session Expiry Interval 0, das heißt, die Session endet mit dem Schließen der Netzwerkverbindung. Für eine Persistent Session in MQTT 5 müssen Sie den Wert explizit setzen.
Was ist der Unterschied zwischen Clean Start und Clean Session?
Clean Session in MQTT 3.1.1 steuerte sowohl das Verwerfen der alten Session als auch das Behalten der neuen. Clean Start in MQTT 5 steuert nur das Verwerfen beim Verbindungsaufbau, während das Session Expiry Interval festlegt, wie lange die Session danach lebt.
Was ist das maximale Session Expiry Interval?
Das Protokollmaximum liegt bei 4.294.967.295 Sekunden (0xFFFFFFFF), was bedeutet, dass die Session nie abläuft. Broker können niedrigere Grenzen festlegen und im CONNACK melden; der öffentliche MQTT-Broker von ConnectMQ erlaubt bis zu 30 Minuten.
Kann ich den Session-Ablauf beim Trennen ändern?
Ja, indem Sie im DISCONNECT eine Session-Expiry-Interval-Property mitsenden, es sei denn, Sie hatten sich ursprünglich mit einem Ablaufwert von 0 verbunden.



