MQTT-Grundlagen

MQTT Client ID Best Practices: Eindeutigkeit, Format und Takeovers

Über die Client-ID weiß ein MQTT-Broker, wer Sie sind. Machen Sie hier Fehler, werfen sich Geräte gegenseitig vom Broker oder verlieren ihre Sessions. Hier sind die Regeln, Formate und Debugging-Schritte, die funktionieren.

Illustration zur MQTT Client ID mit zwei Geräten, die mit derselben Kennung um eine Broker-Verbindung konkurrieren
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

Die MQTT Client ID ist die Kennung, die ein Client im CONNECT-Paket sendet, und der Broker unterscheidet damit Verbindungen und Sessions. Dieser Leitfaden erklärt, warum sich zwei Clients mit derselben ID ständig gegenseitig trennen, wie Sie ID-Formate entwerfen, die vom ersten Prototyp bis zur ganzen Geräteflotte skalieren, und wie Sie Takeovers beim Testen auf einem öffentlichen MQTT-Broker schnell diagnostizieren.

Wofür die MQTT Client ID verwendet wird

Jedes CONNECT-Paket enthält ein Feld Client Identifier. Der MQTT-Broker nutzt es für drei Dinge:

  1. Eindeutigkeit der Verbindung. Pro Client-ID darf jeweils nur eine Netzwerkverbindung aktiv sein.
  2. Session-Zuordnung. Der Zustand einer Persistent Session (Subscriptions und gepufferte Nachrichten) wird unter der Client-ID gespeichert.
  3. Betrieb. Logs, Verbindungsereignisse und Monitoring-Topics bezeichnen Clients über ihre ID.

Sie ist für sich genommen keine Authentifizierungsinformation. Jeder, der sich verbinden kann, kann jede beliebige ID beanspruchen, sofern der Broker IDs nicht an Zugangsdaten bindet. Auf privaten ConnectMQ-Brokern sind Client-IDs an die im Portal ausgestellten Zugangsdaten gebunden, sodass ein anderer Benutzer die ID Ihres Geräts nicht wiederverwenden kann.

Warum sich doppelte Client-IDs gegenseitig hinauswerfen

Die Spezifikation ist eindeutig: Verbindet sich ein Client mit einer ID, die bereits verbunden ist, muss der Broker den bestehenden Client trennen. Das nennt man Session Takeover. Es gibt ihn, damit sich ein Gerät, das seine Verbindung unbemerkt verloren hat, sofort neu verbinden kann, ohne auf das Timeout des alten Sockets zu warten.

Das Problem entsteht, wenn sich zwei verschiedene Clients eine ID teilen. Der Ablauf sieht so aus:

  1. Client A verbindet sich als sensor-01.
  2. Client B verbindet sich als sensor-01. Der Broker trennt A.
  3. Der Auto-Reconnect von A greift und verbindet sich als sensor-01. Der Broker trennt B.
  4. B verbindet sich neu ... und die Schleife wiederholt sich alle paar Sekunden.

Typische Symptome sind ständige Connect/Disconnect-Logs, verpasste Nachrichten, wiederholt ausgelöste Will Messages und eine flackernde Online/Offline-Anzeige. In MQTT 5 erhält der hinausgeworfene Client ein DISCONNECT mit dem Reason Code 0x8E (Session taken over), was die Diagnose deutlich einfacher macht als in 3.1.1, wo der Socket einfach geschlossen wird.

Häufige Ursachen

  • Dasselbe Firmware-Image mit fest codierter ID wird auf viele Boards geflasht.
  • Kopierter Beispielcode mit einer ID wie test oder esp32client.
  • Ein Dienst läuft in mehreren Containern oder Pods mit derselben konfigurierten ID.
  • Ein Entwickler startet dasselbe Skript in zwei Terminals.
  • Ein Desktop-MQTT-Tool und ein Gerät verwenden beide die ID des Geräts.

Ein Format für die MQTT Client ID entwerfen

Gute IDs sind eindeutig, stabil, lesbar und für jeden Broker unbedenklich.

Formatregeln

Regel Warum
Nur a-z, A-Z, 0-9, - und _ verwenden Jeder Broker muss diese Zeichen akzeptieren
Kurz halten, idealerweise 23 Zeichen oder weniger MQTT 3.1.1 garantiert nur bis zu 23 Byte; die meisten Broker erlauben mehr
In der Produktion nie leer lassen Leere IDs verhindern Persistent Sessions, und viele Broker lehnen sie ab
Bei Geräten mit Sessions stabil halten Eine wechselnde ID bedeutet jedes Mal eine neue Session
Pro laufender Instanz eindeutig machen Verhindert Takeover-Schleifen
Keine Geheimnisse oder personenbezogenen Daten IDs erscheinen in Logs und im Monitoring

Bewährte Muster

  • Geräte: ein Präfix plus eine aus der Hardware abgeleitete Kennung, etwa env- plus die letzten Bytes der MAC-Adresse (env-a4cf12b3), oder eine Seriennummer aus Ihrer Fertigungsdatenbank.
  • Edge-Gateways in der Fertigung: ein kurzes Standort- und Linienkürzel plus laufende Nummer, etwa gw-muc-l1-01. Die vollständige Position in der ISA-95-Hierarchie (Enterprise, Site, Area, Line, Cell) gehört dagegen in die Topic-Struktur Ihres Unified Namespace (UNS), etwa acme/werk-muenchen/montage/linie-1/..., nicht in die Client ID; so bleibt die ID kurz und stabil, auch wenn ein Gateway umgezogen wird. Mehr zum UNS unter Sparkplug B und Unified Namespace.
  • Backend-Dienste: Dienstname plus Instanzkennung, etwa alarm-worker-0 aus der Ordinalzahl eines StatefulSets. Sind Instanzen vollständig austauschbar und benötigen keine Sessions, ist ein zufälliges Suffix in Ordnung.
  • Browser-Dashboards: ein Präfix plus eine Zufallszeichenfolge pro Tab, mit Clean Sessions, denn niemand muss die Session eines Dashboards fortsetzen.
  • Testskripte: bei jedem Lauf ein zufälliges Suffix, zum Beispiel test- plus 6 zufällige Hex-Zeichen.

IDs im Code erzeugen

Python, mit der MAC-Adresse für eine stabile Geräte-ID oder einem Zufallstoken für Test-Clients:

import secrets
import uuid
import paho.mqtt.client as mqtt

def device_client_id(prefix: str = "env") -> str:
    mac = uuid.getnode()            # 48-Bit-Hardwareadresse als int
    return f"{prefix}-{mac:012x}"   # z. B. env-a4cf12b3c4d5

def test_client_id(prefix: str = "test") -> str:
    return f"{prefix}-{secrets.token_hex(3)}"  # z. B. test-9f2c1a

client_id = device_client_id()
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
                     client_id=client_id,
                     protocol=mqtt.MQTTv5)
print("Using client ID:", client_id)

ESP32 mit PubSubClient, die ID wird aus der eFuse-MAC abgeleitet:

#include <WiFi.h>
#include <PubSubClient.h>

WiFiClient net;
PubSubClient mqttClient(net);

String makeClientId() {
  uint64_t mac = ESP.getEfuseMac();
  char id[24];
  snprintf(id, sizeof(id), "env-%04x%08x",
           (uint16_t)(mac >> 32), (uint32_t)mac);
  return String(id);
}

void connectMqtt() {
  String clientId = makeClientId();
  mqttClient.setServer("broker.connectmq.com", 1883);
  while (!mqttClient.connected()) {
    if (mqttClient.connect(clientId.c_str())) {
      Serial.println("Connected as " + clientId);
    } else {
      Serial.printf("Failed, state=%d. Retrying in 5 s\n", mqttClient.state());
      delay(5000);
    }
  }
}

Das vollständige Board-Setup einschließlich WLAN finden Sie im ESP32-MQTT-Tutorial.

Leere Client-IDs und zugewiesene Kennungen

MQTT 3.1.1 erlaubt eine Client-ID der Länge null nur mit Clean Session auf true; der Broker erzeugt dann intern eine. MQTT 5 geht weiter: Der Broker liefert im CONNACK einen Assigned Client Identifier zurück, damit der Client seinen Namen kennt. Das ist praktisch für Wegwerf-Clients, schließt aber Persistent Sessions aus, weil Sie sich nicht unter einer Identität neu verbinden können, die Sie nicht selbst kontrollieren. Viele Broker, darunter der öffentliche MQTT-Broker von ConnectMQ, verlangen schlicht eine nicht leere ID, was ohnehin die sicherere Gewohnheit ist.

So erkennen Sie einen Client-ID-Takeover

Hier ist ein reproduzierbarer Test auf dem Öffentlichen MQTT-Broker. Verwenden Sie ein eigenes zufälliges Suffix und denken Sie daran, dass der öffentliche MQTT-Broker für alle lesbar und nur für Tests und Prototypen gedacht ist.

  1. Verbinden Sie sich im ersten Terminal mit einer ID und Debug-Ausgabe:
mosquitto_sub -h broker.connectmq.com -p 1883 -V mqttv5 \
  -i dup-demo-k7q1 -d -t 'connectmq/demo/k7q1/#'
  1. Führen Sie im zweiten Terminal exakt denselben Befehl aus.
  2. Terminal eins wird sofort getrennt; mit -d sehen Sie, wie der Broker die Verbindung schließt. Je nach mosquitto-Version beendet es sich oder verbindet sich neu; im zweiten Fall beginnen die beiden Terminals, sich gegenseitig hinauszuwerfen, genau die oben beschriebene Schleife.
  3. Beobachten Sie in einem dritten Terminal, wie der Broker diesen Client sieht:
mosquitto_sub -h broker.connectmq.com -p 1883 -i watcher-k7q1 -v \
  -t '$SYS/broker/connection/dup-demo-k7q1/state'

Eine kurze Checkliste für die Produktion, wenn Geräte ständig die Verbindung wechseln:

  1. Sammeln Sie die Client-IDs aller verdächtigen Geräte und suchen Sie nach Duplikaten.
  2. Prüfen Sie, ob Disconnect-Reason-Codes 0x8E (Session taken over) anzeigen.
  3. Vergleichen Sie Änderungen des Verbindungsstatus mit den Reconnect-Zeitstempeln jedes Geräts; abwechselnde Muster verraten ein Paar, das um eine ID kämpft.
  4. Schließen Sie Desktop-Tools oder VS-Code-Sitzungen, die möglicherweise die ID eines Geräts verwenden.
  5. Hält das Flattern trotz eindeutiger IDs an, sehen Sie sich stattdessen Keep Alive und Netzwerk-Timeouts an.

MQTT Client IDs in der Produktion

Ein paar Betriebsgewohnheiten verhindern die meisten Client-ID-Vorfälle. Erzeugen Sie IDs bei der Provisionierung statt zur Laufzeit, damit dasselbe Gerät auch nach einem Werksreset immer dieselbe ID erhält. Speichern Sie die ID zusammen mit den Zugangsdaten des Geräts, damit der Support Logeinträge der Hardware zuordnen kann. Wenn Sie ein defektes Gerät ersetzen, entscheiden Sie bewusst, ob das neue Gerät die alte ID (und deren Session) übernimmt oder eine neue erhält. Bei Diensten sollte die Instanzkennung vom Orchestrator kommen und nicht aus einer Konfigurationsdatei, die sich alle Replikate teilen.

Mit wachsenden Flotten sollten Client-IDs Teil Ihres Provisionierungsprozesses sein: Erfassen Sie sie zusammen mit den Seriennummern, leiten Sie sie aus der Hardware ab und verwenden Sie eine ID nie für ein anderes physisches Gerät wieder. Wenn Sie MQTT von Grund auf lernen, erklärt das MQTT-Tutorial, wie IDs, Sessions und Topics zusammenspielen.

Client-IDs sicher mit ConnectMQ verwalten

ConnectMQ ist ein verwalteter MQTT-Broker, der für jeden von Ihnen angelegten Broker Benutzername, Passwort und Client-ID ausstellt und Client-IDs an diese Zugangsdaten bindet, sodass andere Mandanten sie nicht kapern können. Der Verbindungsstatus ist im Portal live sichtbar, wodurch sich Takeover-Schleifen leicht erkennen lassen. Erstellen Sie einen kostenlosen Serverless-Broker ohne Kreditkarte und verbinden Sie sich mit YOUR_USERNAME, YOUR_PASSWORD und YOUR_CLIENT_ID.

Häufig gestellte Fragen

Was passiert, wenn zwei MQTT-Clients dieselbe Client-ID verwenden?

Der Broker trennt den bereits verbundenen Client und behält den neuen. Verbinden sich beide Clients automatisch neu, werfen sie sich in einer Schleife immer wieder gegenseitig hinaus.

Wie lang darf eine MQTT Client ID sein?

MQTT 3.1.1 garantiert 1 bis 23 Byte aus Buchstaben und Ziffern; Broker dürfen längere IDs und weitere Zeichen erlauben. Kurze alphanumerische IDs mit Bindestrichen sind die portabelste Wahl.

Sollte die MQTT Client ID zufällig sein?

Verwenden Sie eine zufällige ID für kurzlebige oder austauschbare Clients, die keine Sessions benötigen. Geräte und Dienste, die auf Persistent Sessions angewiesen sind, brauchen eine stabile, eindeutige ID, die über alle Reconnects gleich bleibt.

Ist die Client-ID eine Sicherheitsinformation?

Nein. Betrachten Sie sie nur als Kennung und authentifizieren Sie sich immer mit Benutzername und Passwort oder Zertifikaten; Broker, die IDs an Zugangsdaten binden, wie ConnectMQ, bieten zusätzlichen Schutz vor Identitätsmissbrauch.

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.