Aus Linux-Magazin 11/2015

MQTT dient dem Admin für viele ungewöhnliche, aber nützliche Anwendungen

© TONO BALAGUER, 123RF

Obwohl das Protokoll MQTT gewöhnlich im selben Atemzug wie das Internet of Things (IoT) erwähnt wird, bietet es Admins mit seinen Features auch ganz andere spannende Verwendungsmöglichkeiten. Zum Beispiel beim Monitoring.

Einst entwickelte IBM das leichtgewichtige TCP-basiertes Protokoll MQTT. Der Name war die Abkürzung für “Message Queueing Telemetry Transport”. Doch seit der Ratifizierung von MQTT als offizieller OASIS-Standard Ende 2014, ist die Langform nicht mehr erlaubt.

MQTT ist ein Pub/Sub-Protokoll (Publish/Subscribe). Clients verbinden sich mit einem Server genannten Broker und können, falls sie autorisiert sind, Nachrichten publizieren oder auf das Eintreffen von Nachrichten warten. MQTT verwendet standardmäßig den TCP-Port 1883 und den TLS-TCP-Port 8883.

Im Gegensatz zu HTTP gibt es hier kein Polling durch den Client, stattdessen informiert der Broker den wartenden Subscriber, sobald eine Nachricht für ihn anliegt, und teilt sie ihm mit. Das spart Bandbreite und ermöglicht eine Kommunikation mit geringer Latenz.

Was die Clients mit den Nachrichten anfangen, das weiß der Broker nicht, sein Job ist zu Ende, sobald die Nachricht zugestellt ist. MQTT ermöglicht eine entkoppelte 1-zu-n- oder 1-zu-1-Beziehung von verschiedenen Geräten oder Programmen, die sich nicht speziell kennen müssen, um dennoch miteinander zu sprechen. Sie müssen nur gegenseitig ihre Dateninhalte verstehen.

MQTT-Clients, sowohl Subscriber als auch Publisher, können jederzeit kommen und gehen. Neue Clients dürfen sich zu jeder Zeit mit dem Server verbinden. Allerdings verfügt ein MQTT-Broker meist über Access Control Listen (ACLs), die den Zugriff auf bestimmte Topics regeln.

Topic, ein Namensstring

Jede Nachricht ist mit einem Topic verbunden. Das sind hierarchisch aufgebaute Namensstrings in UTF-8 mit einer Länge bis zu 64 KByte, die Unix-Pfaden ähneln. Im Unterschied zu Pfadangaben sollte man hier allerdings den führenden Schrägstrich vermeiden, weil er keinen Sinn ergibt. So könnte – um beim Beispiel Internet of Things zu bleiben – etwa eine Lampe ihren Zustand über ein Topic »lampe/kueche/zustand« publizieren, während das Topic »lampe/wohnen/schalter« eine Leuchte im Wohnzimmer ein- oder ausschaltet. Auf demselben Broker kann ein Ventilator seine Befindlichkeit via »klima/ventilator/nummer/1« veröffentlichen.

Will ein bestimmter Client den Zustand der Leuchte im Wohnzimmer erfahren, bestellt er Nachrichten mit »lampe/wohnen/zustand« . Hört er hingegen auf »lampe/+/zustand« , erfährt er, sobald jemand irgendeine Leuchte an- oder ausknipst. Alle Aktivitäten aller Lampen erhält ein Client über »lampe/#« .

Das Sonderzeichen »+« steht für eine Topic-Ebene und darf auch mehrfach vorkommen (»lampe/+/+« ). Das Zeichen »#« darf hingegen nur einmal, und zwar am Ende des Topic, auftauchen und bedeutet “diese Ebene und alle darunterliegenden Topic-Ebenen”. Will ein Client alles sehen, genügt die Angabe »#« . Ob er aber auch wirklich alle Nachrichten sieht, die beim Broker ankommen, das weiß der Client nicht, darüber entscheiden die Broker-ACLs.

Nachrichten transportieren Payloads, also Daten, die auch binär sein können und eine Größe von bis zu 256 MByte haben dürfen. Diese Beschränkung ist eher theoretischer Natur, denn oft sprechen auch Mikrocontroller MQTT, die nur über wenige Kilobyte Speicher verfügen, und für die ist es unmöglich, eine solche Datenmenge zu verarbeiten. Payloads sind häufig einfache Strings (»23« , um eine Temperatur anzugeben) oder in Json verpackte Daten (»{ “celsius” : 23.0 }« ).

Der letzte Wille

Wird eine Nachricht mit einem Topic publiziert, verteilt der Broker sie an alle Subscriber, die auf das Topic horchen. Hört gerade keiner zu, geht die Nachricht verloren – sie wird nicht zwischengespeichert, denn es gibt keine Queue. Um das zu verhindern, kann der Nutzer beim Publizieren ein Retained-Flag setzen, was den Broker dazu veranlasst, die Nachricht zu speichern und künftigen Subscribern anzubieten. Wird zum Beispiel die Außentemperatur auf »temp/terrasse« publiziert und ein Client führt Stunden später ein Subscribe auf dieses Topic aus, so bekommt er sofort diese zuletzt publizierte Temperatur (Last-known Value) geschickt, wenn das Retained-Flag gesetzt war.

Was passiert, wenn ein Client unerwartet ausfällt? Ein wichtiges Feature von MQTT heißt LWT (Last Will and Testament). Ein Client teilt dem Broker beim Verbindungsaufbau mit: “Im Falle meines Ablebens verschicke bitte mit diesem Topic folgende Nachricht …” Erkennt anschließend der Broker, dass dieser Client nicht mehr lebt, tut er wie ihm geheißen und publiziert die Nachricht mit dem gewünschten Topic. So hat MQTT sozusagen ein Monitoring eingebaut: Es ist einfach, Clients zu schreiben, die auf das Ableben anderer Clients reagieren, etwa indem sie Alerts verschicken.

LWT-Nachrichten kommen häufig zusammen mit dem Retained-Flag zum Einsatz, um den Zustand eines Clients dauerhaft zu beschreiben: Beim Start publiziert ein Client mit Retained-Flag zum Beispiel mit dem Topic »clients/id/status« eine Statusnachricht. Beim Ableben dieses Clients würde der Broker in dessen Auftrag ebenfalls mit Retained-Flag und demselben Topic die Nachricht »dead« verbreiten. So ergibt eine Abfrage auf »clients/id/status« jederzeit, ob der Client on- oder offline ist.

Es bietet sich an, einen MQTT-Broker als einen großen Topf zu betrachten, in den Messages purzeln. Jeder kann sich jederzeit aus diesem Topf bedienen. Danach verarbeitet er die Daten und publiziert sie unter Umständen erneut.

Man könnte sich beispielsweise vorstellen, dass ein Temperatursensor periodisch Messwerte in Fahrenheit mit dem Topic »temp/fahrenheit« publiziert. Ein triviales Programm führt ein Subscribe auf dieses Topic aus, liest die Messwerte, konvertiert sie in Grad Celsius und publiziert sie erneut (wirft sie wieder in den Topf), diesmal mit dem Topic »temp/celsius« . Das Programm ist dann gleichzeitig Subscriber und Publisher.

Qualitätskontrolle

MQTT basiert auf TCP und profitiert von dessen hoher Übertragungssicherheit. Dennoch kennt es drei Servicequalitäten, die die Übertragung von Nachrichten sichern. Diese Garantien reichen von gar keiner Zusicherung (Level 0) über die, dass Nachrichten mindestens einmal ankommen (Level 1), bis hin zum Versprechen, dass eine Nachricht exakt einmal eintrifft (Level 2).

Wie aus der Abbildung 1 ersichtlich, sind die drei Quality-of-Service-Stufen (QoS) zunehmend gesprächig: Im Falle von QoS 2 gibt es vier Handshakes zwischen Client und Broker. Im LAN ist QoS 0 gewöhnlich sehr zuverlässig. Werden etwa Telemetriedaten übertragen, reicht QoS 0 häufig aus. Es ist nicht weiter schlimm, wenn die minütlich publizierte Außentemperatur mal ausbleibt – eine Minute später wird sie eh wieder verschickt (QoS 0 genügt). Die Position eines mobilen Geräts will der Anwender vielleicht mit mehr Zuverlässigkeit übertragen (QoS 1 oder 2), obwohl der Netzwerkverkehr und somit die Kosten steigen. Je höher das spezifizierte QoS-Level ist, desto mehr Netzwerkverkehr entsteht.

Abbildung 1: Qualitätskontrollstufen bei MQTT.

Abbildung 1: Qualitätskontrollstufen bei MQTT.

Broker

Von Open-Source-Software bis hin zu teuren Appliances – die Palette an MQTT-Brokern lässt kaum Wünsche offen. Als Open Source sehr bekannt ist Mosquitto [1], ein in C entwickelter, leichtgewichtiger, aber mächtiger Broker mit ACLs, mit in C geschriebenen Authentifizierungs-Plugins und TLS (Transport Layer Security). Mosquitto unterstützt auch Clientauthentifizierung mit TLS-Clientzertifikaten. Selbst wenn er sich in den meisten Repositories findet, empfehlen sich die Pakete von der Projektseite.

Ein neuer Kandidat ist in Erlang geschrieben, heißt Vernemq [2] und beherrscht Clustering als Highlight. Im kommerziellen Umfeld hat sich das in Java geschriebene Hivemq [3] bewährt: Es wartet ebenfalls mit Clustering und einem Plugin-System auf. Alle unterstützen Websockets, auch wenn dies in Mosquitto der Nutzer erst einkompilieren muss.

Die Defaultkonfiguration von Mosquitto eignet sich bestens zum Experimentieren. Der Anwender muss sie erst dann anpassen, wenn er Authentifizierung und TLS hinzufügen will. Er braucht aber weder Topics noch Clients vorzukonfigurieren, kann also direkt loslegen. Für erste Versuche bieten sich die Kommandozeilen-Utilities von Mosquitto an (Listing 1). Ein Subscribe horcht auf alle Topics (»mosquitto_sub« ), und ein Publish vom zweiten Terminal (»mosquitto_pub« ) publiziert eine Nachricht, die beim Subscriber ankommt.

Listing 1

Auf der Kommandozeile

01 # im ersten Terminal
02 mosquitto_sub -v -t '#'
03
04 # im zweiten Terminal
05 mosquitto_pub -t linux/magazin -m "Hello world"
06
07 # mit Retain Flag
08 mosquitto_pub -r -t linux/magazin -m "Hallo Welt"

Wird der Subscriber einfach neu gestartet, erhält er keine alten Nachrichten – die wären bei ihm nur eingetroffen, wäre er vor dem Publisher losgelaufen. Verwendet der Nutzer jedoch wie im letzten Beispiel von Listing 1 das Retained-Flag, dann begrüßt MQTT seine zukünftigen Subscriber zum Topic »linux/magazin« auf Deutsch. Die ältere Nachricht wird in diesem Fall nachgereicht. Bleibt der Subscriber verbunden, dann sieht er auf diesem Topic fortan neue Nachrichten. Verbindet er sich erneut, dann erhält er die Retained-Nachricht und anschließend alle neu ankommenden.

Die Wahl des Brokers ist den eigenen Anforderungen anzupassen: Ist Clustering-Support zwingend oder ist vielleicht eine eigene Lösung mit HA-Proxy nutzbar? Ist Java auf dem System zulässig? Bedarf es kommerziellen Supports? Beherrschen die eigenen Leute die nötigen Programmiersprachen (C, Erlang, Java), um eigene Broker-Plugins zu entwickeln?

Bridges

Nicht alle Client-APIs und somit nicht alle Geräte, die via MQTT kommunizieren, verfügen über alle Protokollfeatures. So sind Mikrocontroller typischerweise aufgrund der mageren Hardware-Ausstattung nicht in der Lage, TLS zu verwenden. Will der Admin dennoch solche Geräte sicher ins Netz bringen, bedient er sich einer Bridge.

In diesem Fall platziert er MQTT-Clients netzwerktechnisch in die Nähe eines Brokers, der dann neben seiner normalen Brokertätigkeit noch die Aufgabe übernimmt, eine konfigurierbare Liste von Topics an entfernte Broker zu senden respektive von diesen zu empfangen und an eigene Clients zu verteilen. Im Falle einer nicht vorhandenen TLS-Unterstützung sind die Clients damit nur auf der kurzen Netzwerkstrecke zum nächstgelegenen Broker ungeschützt.

Eine Bridge muss auch nicht notwendigerweise alle Topics transportieren – stattdessen definiert der Admin, welche Topics sie annehmen und wieder versenden soll. Das ermöglicht fein abgestufte Konfigurationen, die nicht einfach alle Daten herausposaunen. In der Abbildung 2 sind die Clients »P« und »S« in der Lage, untereinander über beide Broker Nachrichten auszutauschen, und der Systemadministrator legt fest, welcher der beiden Broker den anderen zuerst anspricht (Stichwort: Firewall).

Abbildung 2: Eine Brücke zwischen zwei MQTT-Brokern.

Abbildung 2: Eine Brücke zwischen zwei MQTT-Brokern.

Schwieriger wird es, wenn Redundanz ins Spiel kommen soll, wenn also ein zweiter Broker einspringen soll, sobald der erste ausfällt. Mosquitto kann das nicht, aber Vernemq und Hivemq sind mit Clustering-Funktionen ausgestattet. Ob ein Client in einem Zwei-Knoten-Cluster über den Node A oder B publiziert, ist irrelevant – die Nodes versuchen sich als ein Broker darzustellen.

MQTT kann dem Sysadmin in vielen Situationen nützliche Dienste leisten. Hat er beispielsweise ein lange laufendes Shellskript gestartet und will irgendwann später wissen, ob es noch seine Arbeit verrichtet, so kann er das einfach beobachten, wenn im Skript hin und wieder einige Anweisungen wie »mosquitto_pub« eingestreut sind. Sie geben damit Lebenszeichen, die ein kleiner, auf »localhost« horchender Broker leicht empfangen kann. Die triviale Funktion

progname=${progname:=$(basename $0)}
topic="processes/${progname}"
mqtt_opts="--quiet -h localhost -p 1883"
function mqtt() {
   # Ignore PUB errors
   mosquitto_pub ${mqtt_opts} -t "${topic}" -m "$*" || true
}

sorgt im eigenen Skript (Listing 2) dafür, dass man mit einem Subscribe auf dem Broker nach dem Rechten sehen kann.

Listing 2

Beispielskript

01 #!/bin/sh
02
03 source mqttfuncs.sh
04
05 mqtt Start
06
07 # for ... # lange Schleife
08 mqtt "verarbeite jetzt xyz `date`"
09 # done
10
11 mqtt "So, jetzt ist Schluss"

Für Programmierer

Die »mosquitto_*« -Utilities sind für Tests oder zum Einbetten in Shellskripte unerlässlich. Unabhängig davon existieren MQTT-APIs für viele Sprachen, von Java und Javascript über C, C#, Objective-C und Lua bis Perl und Python. Der in Python geschriebene Subscriber aus Listing 3 vereinbart zunächst einen Callback, der aufgerufen wird, sobald eine Nachricht eintrifft. Jetzt verbindet sich der Client mit dem Broker und geht kontrolliert in eine Endlosschleife. Trifft vom Broker eine Nachricht mit dem richtigen Topic ein, wird der Callback ausgeführt, der die Nachricht ausgibt, in eine Datenbank speichert oder Ähnliches.

Listing 3

Subscriber in Python

01 #!/usr/bin/env python
02
03 import paho.mqtt.client as paho   # pip install paho-mqtt
04
05 def on_message(mosq, userdata, msg):
06     print "%s (qos=%s, r=%s) %s" % (msg.topic, str(msg.qos), msg.retain, str(msg.payload))
07
08 mqtt = paho.Client()
09 mqtt.on_message = on_message
10
11 mqtt.connect("localhost", 1883, 60)
12 mqtt.subscribe("linux/+", 0)
13
14 mqtt.loop_forever()

Wer überwachen will, ob der Client noch am Leben ist, fügt einen letzten Willen in das Skript aus Listing 3 ein:

# LWT vereinbaren
mqtt.will_set('alerts/attention', payload="Died: %s" % sys.argv[0], qos=0, retain=False)

Nun erhält der Anwender eine Information, sobald der Client terminiert (etwa nach [Ctrl]+[C]).

Das kleine Projekt »mqttwarn« [4] bietet ein Python-Werkzeug mit vielen Plugins für solch ein Monitoring an (Abbildung 3). Mqttwarn koppelt Topics, auf denen es horcht, mit Services, die es aufruft. Gesteuert wird das Ganze über eine Konfigurationsdatei wie in Listing 4.

Listing 4

Mqttwarn-Konfiguration

01 [defaults]
02 launch   = log, pushover
03
04 [config:log]
05 targets = {
06     'info'   : [ 'info' ],
07   }
08
09 [config:pushover]
10 targets = {
11     'linux'  : ['ml1234567890..', 'buzQx...'],
12   }
13
14 [alerts/attention]
15 targets = pushover:linux, log:info
16 title: Linux Magazin
17 format = {payload}
Abbildung 3: Mqttwarn verschickt gemäß dem letzten Willen eine Warnung über Pushover.

Abbildung 3: Mqttwarn verschickt gemäß dem letzten Willen eine Warnung über Pushover.

Websockets

Moderne Webbrowser können MQTT unter Zuhilfenahme von Websockets benutzen. Das Paho-Projekt [5] stellt ein Javascript-Modul bereit, das dies implementiert. Alle Broker verfügen über Websocket-Unterstützung auf frei konfigurierbaren Ports. Zu beachten ist dabei, dass die Kommunikation über Websockets nicht über den Standard-MQTT-Port 1883 läuft.

Mit Websockets im Browser entfällt die Notwendigkeit, HTTP-Polling oder Refreshes durchzuführen: Der Browser bekommt Nachrichten, sobald MQTT-Clients sie über den Broker publizieren. Das sorgt für interaktive Anwendungen: Mit etwas HTML- und Javascript-Geschick lassen sich interessante Monitoring-Panels entwickeln, die beispielsweise Sensor- oder Positionsdaten von mobilen Geräten in Echtzeit darstellen.

Im richtigen Leben

MQTT wird außerhalb des IoT in verschiedenen Produkten eingesetzt. Für den Statistik-Daemon Collectd [6] existiert seit Kurzem ein MQTT-Plugin genauso wie für das Loggingsystem Graylog [7]. Das Open-Source-Projekt Owntracks [8] stellt I-OS- und Android-Clients bereit, die über MQTT Positionierungsdaten an den eigenen MQTT-Broker liefern; Freunde und Familienmitglieder können dann auf Wunsch gegenseitig sehen, wo sie sich befinden (Abbildung 4). Wer sich mit Heimautomatisierung und Open HAB beschäftigt, kann auch von MQTT profitieren [9]: Es gibt eine Vielzahl von Möglichkeiten, Open HAB über MQTT zu steuern beziehungsweise über MQTT Statusinformation von Open HAB zu beziehen. Und auch bei den ganz Großen ist MQTT im Einsatz: Aufgrund der geringen Latenz hat Facebook beim Messenger auf MQTT gesetzt [10].

Abbildung 4: Owntracks liefert die Positionsdaten von Bekannten über MQTT.

Abbildung 4: Owntracks liefert die Positionsdaten von Bekannten über MQTT.

Mehr zum Thema auf der 10. OSMC

Mehr zu diesem und vielen weiteren spannenden Themen aus dem Bereich Monitoring gibt es vom 16. bis zum 19. November auf der Open Source Monitoring Conference, die die Firma Netways zum nunmehr zehnten Mal in Nürnberg ausrichtet. Anmelden kann man sich hier: https://www.netways.de/nocache/events_schulungen/osmc/anmeldung/

Der Autor

Jan-Piet Mens ist ein unabhängiger Unix/Linux- Berater, Systemadministrator und Autor, der sich seit 1985 vornehmlich mit Infrastrukturthemen beschäftigt. Eine seiner Spezialitäten ist das DNS, zu dem er auch ein Buch verfasst hat. Auch hat er das MQTT-basierte Open-Source-Projekt Owntracks gestartet.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 4 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Nach oben