Evolution der IoT-Kommunikation: MQTT 5

Seite 2: MQTT 5 im Überblick

Inhaltsverzeichnis

Das Technical Committee für MQTT bei OASIS, das für die Spezifizierung von MQTT verantwortlich zeichnet, hatte sich unter anderem folgende Ziele für MQTT 5 gesteckt:

  • Vereinfachungen des Protokolls für hochskalierbare Systeme,
  • verbesserte Fehlerbehandlung und -Reporting,
  • Erweiterbarkeit des Protokolls,
  • Vereinfachungen von Zustandsübergängen,
  • Identifikation und Bereitstellung von Funktionen für gängige Kommunikationsmuster mit MQTT und
  • verbesserte Authentifizierungs- und Autorisierungsmechanismen.

Obwohl MQTT 5 klar als Nachfolger von MQTT 3.1.1 zu sehen ist, ist das neue Protokoll durch die Fülle an Neuerungen nicht rückwärtskompatibel. Für das Zusammenspiel existieren jedoch Broker, die eine Abwärtskompatibilität garantieren, sodass MQTT-3.1.1- mit MQTT-5-Clients im selben System interagieren können.

Dieser Artikel konzentriert sich auf die interessantesten Neuerungen in MQTT 5. Einen detaillierteren, englischsprachigen Überblick über alle Features bietet die Blogserie "MQTT 5 - New Features and Hidden Gems".

MQTT ist seit jeher zustandsbehaftet: Der Broker speichert den Zustand des Clients, die sogenannte Client-Session. Der Kasten "Daten einer MQTT-Session" zeigt, welche Daten eine Session enthält. Durch das Speichern des Zustands am Broker kann sich ein Client jederzeit neu verbinden und seine Session fortführen. Der Broker ist in der Lage, dem Client Nachrichten nachzuliefern, die dieser verpasst hat, als er nicht verbunden war.

Mehr Infos

Daten einer MQTT-Session

Eine MQTT-Session eines konkreten Clients am Broker besteht üblicherweise aus folgenden Daten:

  • Subscriptions: Alle Topic-Abonnements des Clients.
  • Session Data: Metadaten wie Client Identifier und sonstige brokerspezifische Sessiondaten.
  • Queued Offline Messages: Alle MQTT-Nachrichten, die der Client erhalten sollte, während er offline war. Der Client bekommt die Daten ausgeliefert, sobald er sich neu verbindet.
  • Outgoing Message Flow: Alle Quality-of-Service-1- und -2-Flows, die noch nicht abgeschlossen sind. Damit können Broker und Client Message-Delivery-Garantien über Verbindungsabbrüche hinweg garantieren.

Der Broker speichert die Daten, selbst wenn ein Client nicht verbunden ist. Letzterer kann daher jederzeit mit den gespeicherten Daten weiterarbeiten, sobald er sich neu verbindet.

Es gibt jedoch Fälle, in denen ein Client sich nie wieder mit dem Broker verbindet und es für Letzteren legitim wäre, die Session des Clients zu löschen. MQTT 3.1.1 sah diese Funktion nicht vor, auch wenn manche MQTT-Broker wie HiveMQ und mosquitto das Löschen einer Session nach einem bestimmten Zeitintervall ermöglichen.

MQTT 5 erlaubt nun jedem Client, beim Verbindungsaufbau die Time to Live (TTL) mitzuteilen, also die Lebenszeit der Session, wenn der Client offline ist. Der Broker ist damit in der Lage, für jeden Client individuell die Session zu löschen, wenn dieser sich in dem angegebenen Intervall nicht neu am Broker anmeldet. Das spart Ressourcen am Server.

Neben den MQTT-Sessions ist es mit der neuen Version des Protokolls möglich, MQTT-PUBLISH-Nachrichten, die Nutzdaten enthalten, mit einem Ablaufdatum zu versehen. Sobald die Zeit überschritten ist, darf ein Broker eine Nachricht nicht mehr zustellen. Das ist besonders interessant für Szenarien, bei denen viele Clients oft nicht verbunden sind und der Broker die Nachrichten vorhalten soll, bis die Clients sich erneut verbinden. Wenn die Nachrichten abgelaufen sind, kann der Broker sie vorzeitig löschen. Auch wenn die Funktion nicht in MQTT 3.1 und MQTT 3.1.1 enthalten ist, erlauben manche Broker, eine TTL für MQTT-PUBLISH-Nachrichten zu verwenden.

Mit Negative Acknowledgements hält eine von der Community seit langem gewünschte Funktion Einzug in den MQTT-Standard. Damit dürfen zahlreiche MQTT-Pakete Fehlercodes enthalten. Für die meisten Fehlerfälle war es in MQTT 3.1.1 vorgesehen, die Verbindung der Clients zu trennen, falls es sich um vom Client verursachte Fehler handelte.

MQTT 5 bietet nun neben zahlreichen standardisierten Fehlercodes die Option, eine Beschreibung des Fehlers als Text an den Client zurückzugeben. Die Fehlermeldung gibt der Broker als Response-Paket wie PUBACK oder SUBACK an den Client zurück.

Es steht dem Broker frei, die Fehlercodes nicht zu verwenden: Das bisherige Verhalten, die Verbindung von MQTT-Clients direkt ohne weitere Angabe von Gründen zu trennen, ist weiterhin erlaubt und kann aus Sicherheitsgründen in bestimmten Szenarios gewünscht sein, um Angreifern keine unnötigen Hinweise anzubieten.

Während es bei MQTT 3.1.1 ausschließlich DISCONNECT-Pakete vom Client zum Server gab, ist es dem Server nun erlaubt, vor dem Trennen einer Verbindung ein DISCONNECT-Paket an den Client zu senden, um anzuzeigen, dass er die Verbindung im Anschluss trennen wird. Das Paket kann einen Fehlercode enthalten, um dem Client den Grund mitzuteilen. So können Softwareentwickler im Fehlerfall leichter herausfinden, warum der Broker die Verbindung zu ihrem Client getrennt hat.

MQTT versteht sich als Applikations-Transportprotokoll und ist datenagnostisch. Das bedeutet, dass dem Protokoll die Art der übertragenen Daten prinzipiell egal ist: Alle galten bisher bei MQTT als Binärdaten. In der Projektpraxis ist es jedoch in vielen Fällen nötig, dass der Empfänger einer Nachricht genau weiß, um welche Art von Daten es sich handelt und wie sie zu interpretieren sind. Mit MQTT 5 können Clients beim Senden einer MQTT-PUBLISH-Nachricht einen sogenannten Content Type hinzufügen, der die Art der Daten definiert. Dabei lassen sich sowohl standardisierte MIME Types verwenden, wie sie bei HTTP üblich sind, als auch eigene Interpretationshilfen angeben.

Neben dem neuen Header für die Definition eines Content Types kann ein Client mit einem weiteren Header spezifizieren, ob es sich bei den Nutzdaten um binäre Daten oder UTF-8 kodierte Texte handelt. Da MQTT standardmäßig alle versendeten Nutzdaten als Binärdaten behandelt, ist die Option beispielsweise sinnvoll, um dem Empfänger mitzuteilen, dass er die Daten einfach als Text verarbeiten kann oder als Binärdaten interpretieren soll. Auch wenn die Header für Content Type und Payload Format Indicator in vielen Fällen gemeinsam zum Einsatz kommen, ist es nicht erforderlich, einen oder gar beide Header beim Versenden einer Nachricht zu setzen. In Projekten ist davon auszugehen, dass Entwickler aus Wartbarkeitsgründen beide künftig häufig verwenden werden, da sich die Angabe von Content Types unter anderem bei REST-APIs etabliert hat.

MQTT ist ein Protokoll, das auf dem Publish/Subscribe-Pattern aufbaut und darüber den Sender und die Empfänger einer Nachricht entkoppelt. Das Prinzip steht im Kontrast zum Request/Response-Pattern, das unter anderem in HTTP zum Einsatz kommt: Der Client schickt einen Request zum Server, der eine Antwort zurückliefert. Bei MQTT abonniert ein Client Topics am Broker und erhält die für das Abonnement passenden Nachrichten im Push-Verfahren, sobald sie am Broker eintreffen. Zusätzlich kann jeder Client Nachrichten an den Broker senden.

In der Praxis kommt es häufig vor, dass ein Nachrichtenempfänger dem ursprünglichen Absender der Nachricht eine direkte Antwort senden möchte. Das ist vom Protokoll zunächst nicht vorgesehen, lässt sich aber trotzdem mit den Bordmitteln von MQTT 3.1.1 erreichen. Viele Projekte arbeiten beispielsweise mit sogenannten Feedback Topics: Der ursprüngliche Sender einer Nachricht hat ein Abonnement auf ein bestimmtes Antwort-Topic, über das der Empfänger der Nachricht antworten kann.

Da sich das Pattern inzwischen etabliert hat, bietet MQTT 5 die Konvention direkt im Protokoll: Der neue "Response Topic"-Header kann direkt in einem PUBLISH-Paket enthalten sein und informiert den Empfänger der Nachricht, dass er eine Antwort über das definierte Topic senden soll. Entwickler können ein weiteres neues Header-Feld in Verbindung mit dem Request/Response-Pattern verwenden: Das Correlation-Data-Feld können sie nutzen, um Nachrichten auf allgemeine, von mehreren Clients genutzte Response Topics zuzuordnen. Dabei handelt es sich um eine eindeutige Information, die Bestandteil der Kommunikation zwischen den Parteien ist.

Viele MQTT-Broker ermöglichen schon für MQTT 3.1.1 Shared Subscriptions, wie ein Beitrag auf dem HiveMQ-Blog erklärt. Die Funktion ist in vielen Projekten auf eine große Resonanz gestoßen, sodass sie nun mit MQTT 5 offiziell zum Standard gehört. Bei Shared Subscriptions handelt es sich um eine Art des Client-Load-Balancing. Normalerweise bestellt ein einzelner Client ein Abonnement und bekommt vom Broker jede Nachricht auf dem Topic zugestellt. Shared Subscriptions bieten eine Option, die Nachrichten für ein Abonnement auf unterschiedliche Clients aufzuteilen, sodass jeder Client nur ein Subset der Nachrichten erhält.

Das Vorgehen ist besonders interessant für verteilte Microservice-Backend-Systeme, die einen großen Nachrichtenstrom verarbeiten müssen. Wenn das Aufkommen auf einem Topic höher ist, als das System verarbeiten kann, lässt es sich mit Shared Subscriptions auf mehrere Instanzen verteilen: Der Broker schickt die Nachrichten abwechselnd an einen der Clients, die sich eine Subscription teilen. Ein Vorteil an dem Vorgehen ist, dass die Zahl der Clients mit einer Shared Subscription zur Laufzeit skalieren kann. Wird die Last zu hoch, kann ein neuer Client die Shared Subscription abonnieren, und bei niedrigerer Last kann der Client die Subscription wieder über Unsubscription kündigen.

Viele Nutzer standen bei MQTT 3.1.1 vor einer Herausforderung, wenn sie neben den reinen Nutzdaten noch Metadaten an den Empfänger einer Nachricht übermitteln wollten. MQTT 5 bietet mit nutzerspezifischen Metadaten eine von vielen Anwendern gewünschte Funktion. Der neue Standard definiert eine beliebige Anzahl von Headern, die sich in den meisten MQTT-Paketen nutzen lassen. Damit können MQTT-Clients ihre Pakete mit eigenen Key-Value-Paaren anreichern. Dem Empfänger der Nachricht steht es frei, ob er die zusätzlichen Metadaten interpretieren möchte oder nicht. Die User Properties sind hauptsächlich für applikations- und szenariospezifische Eigenschaften gedacht, die der Broker nicht interpretieren soll. Es gibt keine Begrenzung hinsichtlich der maximalen User-Property-Paare, sondern MQTT-Pakete lassen sich mit einer beliebigen Anzahl Eigenschaften anreichern. Die einzige Voraussetzung ist, dass sich die Werte in UTF-8 kodieren lassen. Zum Versand von Binärdaten in Headern eignet sich beispielsweise die Base64-Kodierung.

Darüber hinaus bietet die neue Version des IoT-Protokolls viele kleine und nützliche Neuerungen. Nennenswert sind unter anderem folgende Ergänzungen:

  • Topic Alias: Die Funktion spart Bandbreite, da sie einen kurzen numerischen Alias ergänzt, der bei der Übertragung den langen Topic-Namen ersetzen kann.
  • Flow Control: Clients und Server können bestimmen, wie viele Nachrichten sich parallel verarbeiten lassen.
  • Maximum Packet Size pro Client: Jeder Kommunikationsteilnehmer kann mitteilen, wie groß eine verarbeitbare Nachricht maximal sein darf.
  • AUTH Packet: Die Macher haben ein neues MQTT-Paket eingeführt, das für komplexe Authentifizierungsverfahren wie die im SASL-Framework (Simple Authentication and Security Layer) spezifizierten Verfahren zum Einsatz kommt.
  • Weiterleitung auf andere Broker: MQTT-Broker können einem Client mitteilen, dass er sich mit einem anderen MQTT-Server verbinden sollte.

MQTT 5 ist ein großer Schritt vorwärts, und die Vielzahl neuer Funktionen macht die frische Version attraktiv für neue Projekte. Das bringt die Frage mit sich, ob es sich bereits lohnt, auf die neue Version des Protokolls zu setzen, oder ob man erst einmal bei MQTT 3.1.1 bleiben sollte.

Diese Frage ist nicht pauschal zu beantworten. Zum Zeitpunkt des Artikels (Anfang 2018) lässt sich jedoch feststellen, dass es bisher keine produktionsreife Implementierung einer MQTT-5-Client-Bibliothek gibt und kein Broker MQTT 5 unterstützt. Interessierte können mit den ersten Implementierungen auf MQTT 5 setzen und erste Gehversuche mit dem neuen Protokoll machen. In Produktionsumgebungen ist es dagegen erfahrungsgemäß sinnvoll, die erste Early-Adopter-Welle abzuwarten, bis die Kinderkrankheiten in den Implementierungen ausgemerzt sind.

Der professionelle MQTT-Broker HiveMQ wird im zweiten Quartal 2018 als Early-Adopter-Release mit MQTT-5-Support verfügbar sein, produktionsreife Releases sind für das dritte Quartal geplant. Die Macher des quelloffenen MQTT-Broker mosquitto arbeiten ebenfall an der MQTT-5-Unterstützung.

Um in Projekten flexibel zu bleiben, ist es wichtig, bei der Auswahl des Brokers für das Projekt darauf zu achten, dass er in Zukunft parallel mit MQTT 3.1.1 und 5 arbeiten kann, damit sich der Wechsel auf eine neuere Protokollversion leicht durchführen lässt.