MQTT Offline-Nachrichten sind die Veröffentlichungen, die ein Broker für einen vorübergehend getrennten Subscriber vorhält und zustellt, sobald dieser zurückkommt. Dieser Artikel erklärt genau, welche Nachrichten dafür infrage kommen, welche Limits auf echten Brokern gelten, und führt Sie durch einen reproduzierbaren Test, bei dem Sie Pufferung und Zustellung selbst beobachten können.
Die vier Bedingungen für MQTT Offline-Nachrichten
Pufferung passiert nicht automatisch. Ein Broker puffert eine Nachricht für einen Offline-Client nur, wenn alle folgenden Punkte zutreffen:
| Bedingung | Was Sie prüfen sollten |
|---|---|
| Der Client hat eine Persistent Session | MQTT 3.1.1: cleanSession = false. MQTT 5: Clean Start = false und Session Expiry Interval > 0 |
| Die Session ist nicht abgelaufen | Ablaufzeit von MQTT 5 noch nicht verstrichen, Broker-Limits nicht überschritten |
| Der Client hatte bereits einen passenden Topic-Filter abonniert | Die Subscription muss existieren, bevor er offline ging |
| Der effektive QoS ist 1 oder 2 | Der Zustell-QoS ist der niedrigere Wert aus Publish-QoS und Subscription-QoS |
Ist eine Bedingung nicht erfüllt, wird die Nachricht diesem Client einfach nicht zugestellt. Der Publisher erhält keinen Fehler, weil MQTT Publisher und Subscriber bewusst entkoppelt. Deshalb sind Fehler vom Typ „mein Gerät hat einen Befehl verpasst“ so häufig: Der Publisher sieht ein erfolgreiches PUBACK vom Broker, aber der Broker hatte keinen Grund, die Nachricht für genau diesen Subscriber aufzubewahren.
Und QoS 0?
QoS 0 bedeutet „höchstens einmal“. Die Spezifikation erlaubt einem Broker, QoS-0-Nachrichten für Offline-Sessions zu puffern, schreibt es aber nicht vor, und die meisten Broker tun es nicht. Betrachten Sie QoS 0 als reinen Live-Verkehr. Die Unterschiede zwischen den Stufen behandelt ausführlich der Artikel MQTT-QoS-Stufen erklärt.
Und Retained Messages?
Retained Messages sind ein eigener Mechanismus. Der Broker behält pro Topic die letzte Retained Message und sendet sie an jeden, der abonniert, ob mit oder ohne Session. Sie beantworten die Frage „Was ist der aktuelle Wert?“, nicht „Was habe ich verpasst?“. Ein Client mit Clean Session erhält beim Abonnieren nach dem Neuverbinden zwar den neuesten Retained-Wert, aber keine der Zwischenaktualisierungen. Ein gutes Design nutzt oft beides: Retained Messages für Zustände, gepufferte QoS-1-Nachrichten für Ereignisse und Befehle.
Limits für Offline-Warteschlangen
Jeder Broker begrenzt Warteschlangen, denn ein getrennter Client, der nie zurückkehrt, würde sonst für immer Speicher belegen.
- Lebensdauer der Session. In MQTT 5 bestimmt das Session Expiry Interval, wie lange die Warteschlange überlebt. Läuft es ab, werden gepufferte Nachrichten verworfen. Auf dem öffentlichen MQTT-Broker broker.connectmq.com, der für Tests und Prototypen gedacht ist, ist der Session-Ablauf auf 30 Minuten begrenzt. Die Wahl der Werte behandelt der Artikel zum MQTT Session Expiry Interval.
- Tiefe der Warteschlange. Broker begrenzen die Anzahl gepufferter Nachrichten oder Bytes pro Session. Wird die Grenze erreicht, werden je nach Broker neue Nachrichten verworfen oder alte verdrängt.
- Message Expiry. Ein MQTT-5-Publisher kann ein Message Expiry Interval setzen. Liegt eine Nachricht länger als diese Zeit in der Warteschlange, verwirft der Broker sie, statt veraltete Daten zuzustellen.
- Nachrichtengröße. Tarif- und Broker-Limits für die Nachrichtengröße gelten auch für gepufferte Nachrichten (64 KB auf dem öffentlichen MQTT-Broker, 256 KB im ConnectMQ-Tarif Serverless Free, 1 MB im kostenpflichtigen Serverless-Tarif).
- Broker-Neustarts. Wo Warteschlangen liegen, hängt vom Broker ab. ConnectMQ hält Sessions und ihre Warteschlangen im Arbeitsspeicher: Sie überstehen Client-Trennungen für die gewährte Session-Lebensdauer, bleiben aber über einen Broker-Neustart hinweg nicht erhalten. Clients sollten eine verlorene Session erkennen (Session Present = 0 im CONNACK), erneut abonnieren und sich für Zustände auf Retained Messages oder eine Resynchronisierung auf Anwendungsebene verlassen.
Reproduzierbarer Test: Offline-Zustellung live beobachten
Dieser Test dauert mit den mosquitto-Kommandozeilentools etwa fünf Minuten. Ersetzen Sie q5t9 durch eine eigene Zufallszeichenfolge und halten Sie die Payloads harmlos: Der öffentliche Bereich ist für alle lesbar.
- Session anlegen. Verbinden Sie einen Subscriber mit fester ID, Clean Start false, 15 Minuten Session-Ablauf und QoS 1:
mosquitto_sub -h broker.connectmq.com -p 1883 -V mqttv5 \
-i offline-sub-q5t9 -c -x 900 -q 1 -v \
-t 'connectmq/demo/q5t9/cmd/#'
Offline gehen. Drücken Sie Strg+C.
Nachrichten mit gemischten QoS-Stufen veröffentlichen, während der Subscriber weg ist:
H="-h broker.connectmq.com -p 1883 -V mqttv5 -i offline-pub-q5t9"
mosquitto_pub $H -q 0 -t 'connectmq/demo/q5t9/cmd/a' -m 'qos0 message'
mosquitto_pub $H -q 1 -t 'connectmq/demo/q5t9/cmd/b' -m 'qos1 message'
mosquitto_pub $H -q 1 -t 'connectmq/demo/q5t9/cmd/c' -m 'short-lived' \
-D publish message-expiry-interval 5
mosquitto_pub $H -q 1 -t 'connectmq/demo/q5t9/other' -m 'not subscribed'
- Warten Sie mindestens 10 Sekunden und führen Sie dann den Befehl aus Schritt 1 erneut aus.
Sie sollten nur connectmq/demo/q5t9/cmd/b qos1 message sehen. Deshalb fehlen die anderen:
cmd/ahatte QoS 0 und wurde daher nicht gepuffert.cmd/chatte eine Message Expiry von 5 Sekunden und wurde in der Warteschlange verworfen.otherpasste nicht zum Subscription-Filter.
- Wiederholen Sie Schritt 1 ohne
-c. Beim Neuverbinden wird nichts zugestellt, weil die Session beim Schließen der Verbindung verworfen wurde.
Dasselbe Muster in Python
Ein Gerät, das sich neu verbindet und alles verarbeitet, was es verpasst hat:
import paho.mqtt.client as mqtt
from paho.mqtt.properties import Properties
from paho.mqtt.packettypes import PacketTypes
TOPIC = "connectmq/demo/q5t9/cmd/#"
def on_connect(client, userdata, flags, reason_code, properties):
if reason_code.is_failure:
print("Connect failed:", reason_code)
return
print("Connected. Session present:", flags.session_present)
if not flags.session_present:
# Neue oder verlorene Session: abonnieren und Zustand auf anderem Weg holen
client.subscribe(TOPIC, qos=1)
def on_message(client, userdata, msg):
print(f"Processing {msg.topic}: {msg.payload.decode()}")
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
client_id="offline-py-q5t9",
protocol=mqtt.MQTTv5)
client.on_connect = on_connect
client.on_message = on_message
client.reconnect_delay_set(min_delay=1, max_delay=60)
props = Properties(PacketTypes.CONNECT)
props.SessionExpiryInterval = 900
client.connect("broker.connectmq.com", 1883, keepalive=60,
clean_start=False, properties=props)
client.loop_forever()
Design für Offline-Clients
Pufferung hilft bei kurzen Lücken, sollte aber nicht Ihr einziges Werkzeug für Zuverlässigkeit sein. Ein robustes Design kombiniert mehrere Mechanismen:
- Verwenden Sie QoS 1 für Befehle und Ereignisse, QoS 0 für hochfrequente Telemetrie, bei der der nächste Messwert den letzten ersetzt. In der Fertigung sind das etwa Auftragsdaten vom MES und Störmeldungen einerseits, zyklische Maschinendaten andererseits.
- Halten Sie den Session-Ablauf realistisch. Lang genug für typische Ausfälle, kurz genug, damit tote Geräte keine Warteschlangen anhäufen.
- Setzen Sie Message Expiry bei zeitkritischen Befehlen, damit ein Gerät, das nach einer Stunde zurückkehrt, keine veraltete Anweisung ausführt.
- Veröffentlichen Sie Zustände als Retained Messages, damit sich jeder Client sofort resynchronisieren kann, ohne von einer Warteschlange abzuhängen. In einem Unified Namespace (UNS) nach ISA-95 ist das der Normalfall: Der aktuelle Zustand jeder Maschine liegt retained an ihrem Knoten, etwa
acme/werk-stuttgart/montage/linie-1/zelle-3/status, und ein SCADA- oder MES-Client, der nach einer Wartung zurückkommt, sieht sofort das aktuelle Bild des Werks. - Machen Sie Handler idempotent. QoS 1 kann nach Reconnects Duplikate zustellen; nehmen Sie eine Nachrichten-ID oder Sequenznummer in die Payload auf.
- Behandeln Sie Session Present = 0 als normales Ereignis, nicht als Fehler.
- Rechnen Sie mit einer Welle beim Neuverbinden. Clients, die offline waren, können viele Nachrichten auf einmal erhalten; Receive Maximum in MQTT 5 begrenzt, wie viele unbestätigte Nachrichten parallel eintreffen.
Hintergründe zu Sessions selbst lesen Sie unter MQTT Persistent Sessions und das Clean-Session-Flag. Wenn Sie gerade erst einsteigen, behandelt das MQTT-Tutorial zuerst die Grundlagen von Publish/Subscribe.
Fehlerbehebung bei fehlenden Offline-Nachrichten
- Nach dem Neuverbinden kommt nichts an: Prüfen Sie, ob die Client-ID identisch ist, Clean Start false ist und in MQTT 5 der Session-Ablauf ungleich null ist.
- Manche Nachrichten kommen an, andere nicht: Vergleichen Sie den QoS jedes Publishs mit dem der Subscription und prüfen Sie auf Message Expiry.
- Nachrichten kommen doppelt an: Das ist bei QoS 1 nach einer unterbrochenen Bestätigung zu erwarten; deduplizieren Sie in der Anwendung.
- Session Present ist unerwartet 0: Die Session ist abgelaufen, die Client-ID hat sich geändert oder der Broker wurde neu gestartet.
Offline-Nachrichten mit ConnectMQ puffern
ConnectMQ ist ein verwalteter MQTT-Broker, der Persistent Sessions, Session Expiry und Message Expiry für MQTT-5.0- ebenso wie für MQTT-3.1.1-Clients unterstützt. Der Tarif Serverless Free unterstützt QoS bis 1, was für Offline-Pufferung völlig ausreicht; QoS 2 ist in den kostenpflichtigen Tarifen verfügbar. Erstellen Sie Ihren kostenlosen Broker ohne Kreditkarte, verbinden Sie sich mit YOUR_USERNAME, YOUR_PASSWORD und YOUR_CLIENT_ID und führen Sie den obigen Test gegen Ihren eigenen privaten Endpunkt aus. Wenn Sie Anbieter vergleichen, lesen Sie, worauf es bei einem Cloud-MQTT-Broker ankommt.
Häufig gestellte Fragen
Speichert MQTT Nachrichten, wenn der Subscriber offline ist?
Nur wenn der Subscriber eine Persistent Session hat, bereits ein passendes Topic abonniert hatte und der effektive QoS 1 oder 2 ist. Andernfalls wird die Nachricht für diesen Client nicht aufbewahrt.
Warum gehen meine QoS-0-Nachrichten verloren, während das Gerät offline ist?
QoS-0-Nachrichten werden für Offline-Sessions normalerweise nicht gepuffert; die Spezifikation macht das optional. Veröffentlichen und abonnieren Sie mit QoS 1, wenn die Nachricht eine Trennung überstehen muss.
Wie lange bewahrt ein Broker Offline-Nachrichten auf?
Bis die Session abläuft, ein Warteschlangen-Limit erreicht ist, die eigene Ablaufzeit der Nachricht verstreicht oder der Broker neu startet, sofern Sessions im Arbeitsspeicher liegen. Bei ConnectMQ liegen Sessions im Arbeitsspeicher, und der öffentliche MQTT-Broker begrenzt den Session-Ablauf auf 30 Minuten.
Ersetzen Retained Messages die Offline-Pufferung?
Nein. Eine Retained Message liefert einem neuen Subscriber den neuesten Wert eines Topics, während die Offline-Pufferung jede QoS-1- oder QoS-2-Nachricht zustellt, die der Client verpasst hat. Die meisten Systeme nutzen beides.



