MQTT Maximum QoS ist der Teil von Quality of Service, der am meisten überrascht: Sie können mit QoS 2 veröffentlichen und eine Nachricht trotzdem mit QoS 0 empfangen. Welche Stufe bei einer Zustellung tatsächlich verwendet wird, hängt vom Publisher, vom Subscriber und von den Grenzen des Brokers ab. In diesem Artikel erfahren Sie, wie der effektive QoS berechnet wird, wie Broker ein Maximum ankündigen und durchsetzen und wie Sie genau testen, was Ihre Verbindung erhält.
QoS wird pro Teilstrecke ausgehandelt
MQTT kennt drei QoS-Stufen: 0 (höchstens einmal), 1 (mindestens einmal) und 2 (genau einmal). Wenn Ihnen diese neu sind, beginnen Sie mit MQTT-QoS-Stufen erklärt.
Entscheidend ist: QoS gilt nicht Ende-zu-Ende. Eine Nachricht durchläuft zwei getrennte Teilstrecken:
- Publisher zum Broker, mit dem QoS, den der Publisher für dieses PUBLISH gewählt hat.
- Broker zu jedem Subscriber, mit einem QoS, den der Broker für diese Subscription berechnet.
Jede Teilstrecke hat ihren eigenen Handshake. Das PUBACK des Publishers kommt vom Broker, nicht vom Subscriber. Ein Publisher weiß also nie, ob irgendein Subscriber die Nachricht erhalten hat.
Wie der effektive QoS berechnet wird
Für jeden Subscriber stellt der Broker mit dem niedrigeren von zwei Werten zu: dem QoS des eingehenden PUBLISH und dem für die passende Subscription gewährten QoS.
| Publish-QoS | Subscription-QoS | Zugestellter QoS |
|---|---|---|
| 0 | 2 | 0 |
| 1 | 0 | 0 |
| 1 | 2 | 1 |
| 2 | 1 | 1 |
| 2 | 2 | 2 |
Zwei Konsequenzen sind in der Praxis wichtig:
- Ein Subscribe mit QoS 2 hebt nichts an. Veröffentlicht ein Sensor mit QoS 0, erhält jeder Subscriber QoS 0, egal was er angefordert hat.
- Ein Subscriber kann bewusst herabstufen. Ein Dashboard, das nur den neuesten Wert braucht, kann mit QoS 1 veröffentlichte Telemetrie mit QoS 0 abonnieren und spart so Bestätigungen auf der eigenen Verbindung.
Überschneiden sich zwei Subscription-Filter (zum Beispiel plant/# und plant/line1/+), stellt der Broker die Nachricht je nach Implementierung einmal mit dem höchsten passenden QoS zu oder in MQTT 5 einmal pro Subscription. Vermeiden Sie nach Möglichkeit überlappende Subscriptions mit unterschiedlichem QoS. In einem Unified Namespace (UNS) nach ISA-95 passiert das schnell, wenn ein MES den ganzen Standort (acme/werk-stuttgart/#) und zusätzlich eine einzelne Linie mit anderem QoS abonniert. Legen Sie den QoS besser pro Teilbaum und Datenart fest.
Wie Broker den QoS begrenzen
Ein Broker muss nicht jede Stufe für jeden Client unterstützen. Er hat zwei Mechanismen, um das mitzuteilen.
Gewährter QoS im SUBACK. Wenn ein Client abonniert, antwortet der Broker mit einem SUBACK, das den gewährten QoS für jeden Filter enthält. Er darf eine niedrigere Stufe als angefordert gewähren. In MQTT 3.1.1 lauten die Rückgabecodes 0, 1, 2 oder 0x80 für einen Fehler; in MQTT 5 sind es Reason Codes, wobei 0x00, 0x01 und 0x02 für gewährten QoS 0, 1 und 2 stehen. Ein gut geschriebener Client prüft diesen Wert, statt anzunehmen, dass seiner Anfrage entsprochen wurde.
Maximum QoS im CONNACK (MQTT 5). Ein MQTT-5-Broker, der QoS 2 oder QoS 1 und 2 nicht unterstützt, fügt dem CONNACK eine Maximum-QoS-Property hinzu. Fehlt die Property, wird QoS 2 unterstützt. Ein Client, der dennoch oberhalb des angekündigten Maximums veröffentlicht, verletzt das Protokoll, und der Broker trennt ihn mit Reason Code 0x9B (QoS not supported). In MQTT 3.1.1 gibt es diese Property nicht, Clients merken es also erst auf die harte Tour.
Broker begrenzen den QoS aus guten Gründen: QoS 2 erfordert mehr gespeicherten Zustand und vier Pakete pro Nachricht auf jeder Teilstrecke, was sich auf geteilter, mandantenfähiger Infrastruktur summiert.
MQTT Maximum QoS auf dem öffentlichen MQTT-Broker testen
Der öffentliche MQTT-Broker unter broker.connectmq.com unterstützt QoS 0 bis 2 und eignet sich daher gut, um Downgrades durch die Kombination aus Publish und Subscribe zu beobachten. Er ist für Tests und Prototypen gedacht, nicht für Produktionsdaten. Mit dem Flag -d geben die Mosquitto-Tools Protokollpakete aus, einschließlich des gewährten QoS im SUBACK.
Terminal 1, Subscribe mit angefordertem QoS 1:
mosquitto_sub -d -h broker.connectmq.com -p 1883 -i mq-sub-u3x7 -q 1 \
-t 'connectmq/demo/u3x7/#' -F 'qos=%q %t %p'
Suchen Sie in der Debug-Ausgabe nach einer Zeile wie Client mq-sub-u3x7 received SUBACK, gefolgt von Subscribed (mid: 1): 1. Die letzte Zahl ist der gewährte QoS.
Terminal 2, Publish auf jeder Stufe:
for q in 0 1 2; do
mosquitto_pub -h broker.connectmq.com -p 1883 -i mq-pub-u3x7 -q $q \
-t connectmq/demo/u3x7/test -m "published at qos $q"
done
Terminal 1 gibt qos=0, qos=1 und qos=1 aus. Das Publish mit QoS 2 wurde auf dem Weg zu diesem Subscriber auf 1 herabgestuft, weil die Subscription genau das angefordert hat. Starten Sie den Subscriber mit -q 2 neu, und die dritte Zeile lautet qos=2.
Gewährten und maximalen QoS im Code prüfen
Dieses paho-mqtt-2.x-Skript verbindet sich per MQTT 5, gibt das vom Broker angekündigte Maximum QoS aus (falls vorhanden), abonniert mit QoS 2 und zeigt, was gewährt wurde:
import uuid
import paho.mqtt.client as mqtt
BROKER = "broker.connectmq.com"
TOPIC = "connectmq/demo/u3x7/check"
def on_connect(client, userdata, flags, reason_code, properties):
max_qos = getattr(properties, "MaximumQoS", None)
if max_qos is None:
print("CONNACK: no Maximum QoS property, QoS 2 supported")
else:
print(f"CONNACK: broker maximum QoS is {max_qos}")
client.subscribe(TOPIC, qos=2)
def on_subscribe(client, userdata, mid, reason_code_list, properties):
rc = reason_code_list[0]
if rc.is_failure:
print("subscription refused:", rc)
else:
print(f"SUBACK: requested 2, granted {rc.value}")
client.disconnect()
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
client_id=f"qoscheck-{uuid.uuid4().hex[:8]}",
protocol=mqtt.MQTTv5)
client.on_connect = on_connect
client.on_subscribe = on_subscribe
client.connect(BROKER, 1883, keepalive=30)
client.loop_forever()
Führen Sie dasselbe Skript mit Ihren echten Zugangsdaten gegen Ihren Produktions-Broker aus, bevor Sie sich auf eine QoS-Stufe verlassen. Es dauert Sekunden und erspart Rätselraten.
QoS bei Retained- und Will-Nachrichten
Dieselbe Minimum-Regel gilt für Nachrichten, die der Broker von sich aus sendet. Eine Retained Message wird mit dem QoS gespeichert, mit dem sie veröffentlicht wurde, und ein neuer Subscriber erhält sie mit dem niedrigeren Wert aus diesem QoS und seinem gewährten Subscription-QoS. Ein Last Will wird mit dem im CONNECT gesetzten Will-QoS veröffentlicht, und jeder Subscriber erhält ihn wiederum mit dem niedrigeren der beiden Werte. Liegt das Maximum QoS des Brokers unter dem angeforderten Will-QoS, kann ein MQTT-5-Broker die Verbindung mit Reason Code 0x9B ablehnen. Halten Sie den Will-QoS daher innerhalb des angekündigten Limits.
Praktische Checkliste
- Legen Sie den QoS pro Topic danach fest, was eine verlorene oder doppelte Nachricht kostet. In der Fertigung heißt das oft: zyklische Maschinendaten mit QoS 0, Alarme, Zählerstände für die OEE und Auftragsdaten vom MES mit QoS 1.
- Veröffentlichen Sie mit diesem QoS; Subscriber können ihn nicht anheben.
- Prüfen Sie den gewährten QoS im SUBACK und protokollieren Sie, wenn er niedriger als angefordert ist.
- Lesen Sie bei MQTT 5 das Maximum QoS aus dem CONNACK und begrenzen Sie Ihre Publishes darauf.
- Entwerfen Sie Consumer für den QoS, den Sie tatsächlich erhalten: idempotent bei QoS 1 (siehe doppelte MQTT-Nachrichten), lückentolerant bei QoS 0.
- Vermeiden Sie überlappende Subscriptions mit unterschiedlichem QoS auf demselben Client.
QoS-Probleme beheben
Client wird direkt nach dem Publish getrennt. Lautet der Reason Code 0x9B, haben Sie oberhalb des Broker-Maximums veröffentlicht. Senken Sie den QoS oder wechseln Sie zu einem Plan oder Broker, der ihn unterstützt. Die vollständige Liste der Codes finden Sie unter MQTT Reason Codes.
Subscriber erhält QoS 0, obwohl er mit QoS 1 abonniert hat. Der Publisher verwendet QoS 0. Beheben Sie das an der Quelle.
Bibliothek meldet Erfolg, aber Nachrichten gehen verloren. Manche Bibliotheken ignorieren den gewährten QoS. Prüfen Sie das SUBACK selbst wie im obigen Skript.
QoS 2 ist langsam. Jede Nachricht braucht vier Pakete pro Teilstrecke. Für Telemetrie mit hoher Rate bietet QoS 1 mit Deduplizierung meist einen besseren Durchsatz.
Die normativen Regeln stehen in der OASIS-MQTT-5.0-Spezifikation, in den Abschnitten zu den SUBACK- und CONNACK-Properties.
QoS-Limits in den ConnectMQ-Plänen
ConnectMQ legt den QoS pro Plan klar offen. Der kostenlose Serverless-Plan unterstützt QoS bis 1, der kostenpflichtige Serverless-Plan ergänzt QoS 2 sowie größere Nachrichten und Shared Subscriptions, und die Optionen Dedicated, BYOC und Self Managed Enterprise bieten Ihnen einen isolierten Cluster. Der öffentliche MQTT-Broker erlaubt für Experimente QoS 0 bis 2. Führen Sie das Prüfskript mit Ihren ConnectMQ-Zugangsdaten aus, um zu bestätigen, was Ihre Verbindung meldet. Wenn Sie Anbieter vergleichen, sind unsere Übersicht zum verwalteten MQTT-Broker und das MQTT-Tutorial gute nächste Lektüre.
Starten Sie mit ConnectMQ
Erstellen Sie unter app.connectmq.com kostenlos einen Broker im Serverless-Plan, ganz ohne Kreditkarte. Beginnen Sie mit QoS 0 und 1 und wechseln Sie in den kostenpflichtigen Plan für QoS 2, sobald die Workload auf Ihrem Cloud-MQTT-Broker eine Exactly-once-Zustellung benötigt.
Häufig gestellte Fragen
Was ist der effektive QoS bei MQTT?
Es ist der QoS, mit dem eine Nachricht an einen Subscriber zugestellt wird: der niedrigere Wert aus Publish-QoS und gewährtem Subscription-QoS.
Kann ein Subscriber einen höheren QoS erhalten, als der Publisher verwendet hat?
Nein. Eine mit QoS 0 veröffentlichte Nachricht wird immer mit QoS 0 zugestellt, unabhängig von der Subscription.
Wie erfahre ich das Maximum QoS des Brokers?
Lesen Sie in MQTT 5 die Maximum-QoS-Property im CONNACK; fehlt sie, wird QoS 2 unterstützt. In MQTT 3.1.1 prüfen Sie den gewährten QoS im SUBACK.
Was passiert, wenn ich oberhalb des Maximum QoS veröffentliche?
Ein MQTT-5-Broker trennt den Client mit Reason Code 0x9B, QoS not supported.



