MQTT-Grundlagen

MQTT Offline-Nachrichten: So puffern Broker Nachrichten für getrennte Clients

MQTT-Broker können Nachrichten für vorübergehend getrennte Clients vorhalten, allerdings nur unter bestimmten Bedingungen. Lernen Sie die Regeln, die Limits und einen reproduzierbaren Test kennen, den Sie in fünf Minuten durchführen.

Illustration zu MQTT Offline-Nachrichten mit einer Broker-Warteschlange, die QoS-1-Nachrichten für ein getrenntes IoT-Gerät bis zum Neuverbinden vorhält
Probieren Sie es auf Ihrem eigenen MQTT-Broker ausHolen Sie sich im Free-Tarif einen privaten, verwalteten MQTT-Broker und starten Sie mit fertigen Codebeispielen.
Kostenlos testen Codebeispiele Keine Kreditkarte erforderlich

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.

  1. 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/#'
  1. Offline gehen. Drücken Sie Strg+C.

  2. 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'
  1. 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/a hatte QoS 0 und wurde daher nicht gepuffert.
  • cmd/c hatte eine Message Expiry von 5 Sekunden und wurde in der Warteschlange verworfen.
  • other passte nicht zum Subscription-Filter.
  1. 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:

  1. 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.
  2. Halten Sie den Session-Ablauf realistisch. Lang genug für typische Ausfälle, kurz genug, damit tote Geräte keine Warteschlangen anhäufen.
  3. Setzen Sie Message Expiry bei zeitkritischen Befehlen, damit ein Gerät, das nach einer Stunde zurückkehrt, keine veraltete Anweisung ausführt.
  4. 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.
  5. Machen Sie Handler idempotent. QoS 1 kann nach Reconnects Duplikate zustellen; nehmen Sie eine Nachrichten-ID oder Sequenznummer in die Payload auf.
  6. Behandeln Sie Session Present = 0 als normales Ereignis, nicht als Fehler.
  7. 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.

Verwandte Artikel

Wer hat MQTT erfunden? Die Geschichte von Ölpipelines bis zum IoT

MQTT wurde 1999 von Andy Stanford-Clark (IBM) und Arlen Nipper (Arcom) erfunden, um Ölpipelines per Satellit zu überwachen. Verfolgen Sie den Weg zu Open Source, OASIS, ISO und den heutigen verwalteten MQTT-Brokern in der Cloud.

8 Min. Lesezeit

Alle Artikel →

Ihr privater MQTT-Broker ist nur wenige Klicks entfernt

Konto anlegen, Broker-Zugangsdaten erhalten und das erste Gerät verbinden — ohne Server, die installiert, gepatcht oder skaliert werden müssen.