IoT Data Streaming – Warum MQTT und Kafka eine exzellente Kombination sind
Eine schnelle und effiziente Integration von Endgeräte-Daten in datenverarbeitende Systeme wird im Internet der Dinge zunehmend wichtiger. Dabei spielen Faktoren wie eine sichere und zuverlässige Datenübermittlung, die Datenverarbeitung in Echtzeit, sowie die Analyse riesiger Datenmengen im Nachgang eine große Rolle. Zur Realisierung einer Architektur, die eine reibungslose Kommunikation zwischen Endgeräten und Systemen ermöglicht, werden Kommunikationsprotokolle benötigt, welche die genannten Faktoren berücksichtigen. MQTT, das De-facto-Standard-Kommunikationsprotokoll für das Internet der Dinge und Apache Kafka, das häufig für Data Streaming im Internet der Dinge verwendet wird, sind Technologien, die man sich im Zuge einer architekturellen Planung eines IoT-Projekts genauer ansehen muss. Dabei spielen die Fragen, welche der Technologien am besten geeignet ist und wo sie am besten eingesetzt werden können, eine entscheidende Rolle.
Technische Herausforderungen im Internet der Dinge
Im Gegenzug zu herkömmlichen Enterprise-Projekten birgt ein Projekt im Internet der Dinge andere technische Herausforderungen. Bereits bei der Planung des IoT-Projekts lohnt es sich, diese einmal genauer zu betrachten. Beispielsweise hat ein typisches Projekt im Internet der Dinge die Herausforderung, potentiell Millionen von Geräten miteinander zu verbinden. Denkt man an ein allgegenwärtiges und geläufiges IoT-Projekt wie das Connected Car, dann hat man eine ungefähre Vorstellung davon, wie viele Geräte typischerweise miteinander verbunden werden. Schwerwiegender als die Anzahl der verbundenen Clients ist jedoch die Menge an Daten, die ausgetauscht wird. Grundsätzlich gesagt, Skalierung ist eine der Hauptherausforderungen in jedem größeren IoT-Projekt.
Bei vielen IoT-Projekten handelt es sich um Anwendungen, die darauf angewiesen sind, Informationen in Echtzeit und ohne Verzögerung zu verarbeiten. Kritische Systeme, wie Fertigungssysteme, basieren auf der sofortigen Zustellung von Daten und Nachrichten. Zum Beispiel kann eine akkurate Überwachung der Systeme einer Fertigungshalle helfen, Fehler frühzeitig zu erkennen und katastrophale Auswirkungen zu verhindern. Aber auch Endnutzer erwarten eine sofortige Zustellung von Nachrichten und Informationen. Möchte ein Autobesitzer beispielsweise sein Auto mittels Handy-App verriegeln, so erwartet er, dass dieses sofort verriegelt ist und die Nachricht nicht erst Minuten später beim Auto ankommt.
Anders als bei den meisten herkömmlichen Projekten handelt es sich bei IoT-Projekten um die Datenübertragung von zumeist beweglichen Geräten. Diese können sich nicht auf ein stationäres, zuverlässiges Netzwerk verlassen, sondern sind ständig wechselnden, unterschiedlichen und dadurch unzuverlässigen Netzwerkverbindungen ausgesetzt. Netzwerkverbindungsabbrüche und schlechte oder gar keine Verbindung müssen von der IoT-Applikation kompensiert werden, um dem Endnutzer eine exzellente User Experience zu bieten. Da es sich meist um bewegliche Geräte handelt, zu denen ein physischer Zugriff nach ihrer Auslieferung an den Endnutzer oftmals nicht mehr möglich ist, besteht zusätzlich die Herausforderung, die Komplexität der Applikation nicht auf den Geräten zu halten, sondern in eine zentrale Komponente in die Cloud zu legen, zu der ein Zugriff jederzeit möglich ist.
MQTT als Standardprotokoll für das Internet der Dinge
Um ein Projekt im Internet der Dinge zu realisieren, braucht man Technologien, die die eben genannten Herausforderungen adäquat angehen. Herkömmliche Web-Technologien wie HTTP u. ä. sind allerdings nicht oder nur sehr eingeschränkt für das Internet der Dinge geeignet. Es braucht neue, offene Standards, die explizit für das Internet der Dinge und seine spezifischen Anforderungen konzipiert sind.
1999 erfanden Andy Stanford-Clark (IBM) und Arlen Nipper (Arcom, jetzt Cirrus Link) den offenen Standard MQTT, um ihr damaliges IoT-Projekt (Ölpipelines mit Satelliten zu verbinden) zu realisieren. Beim Design des Protokolls legten sie explizit Wert darauf, dass Nachrichten schnell und unverzüglich übertragen werden, wobei es ihnen wichtig war, den Ressourcenverbrauch so gering wie möglich zu halten. Durch dieses Protokolldesign wird es auch Maschinen und ressourcenarmen Geräten ermöglicht, problemlos miteinander zu kommunizieren. Neben dem ressourcensparenden Design achteten beide MQTT-Erfinder auch darauf, dass eine zuverlässige Kommunikation über unzuverlässige Netzwerke möglich ist – auch in extremen Skalierungen.
MQTT ist seither das De-facto-Standardprotokoll für das Internet der Dinge, das seit Oktober 2014 auch als offizieller OASIS-Standard geführt wird. Neben den anfänglichen Ölpipelines gesellen sich inzwischen unter anderem auch die Automobilbranche mit dem Connected Car, die Industrie 4.0 mit vernetzten Fabriken, die Logistikbranche mit vernetzen LKWs und Transportwegen und viele weitere Branchen mit interessanten Anwendungsfällen hinzu.
MQTT als IoT-Messaging-Protokoll basiert auf einer Publish-/Subscribe-Architektur, bei der zwischen zwei Arten von Kommunikationsteilnehmern unterschieden wird: Client und Broker.
- Unter den Clients versteht man im Allgemeinen die Dinge, die im Internet der Dinge miteinander kommunizieren, wie Sensoren, Autos oder Maschinen jeglicher Art. Aber auch Backend-Services können als MQTT Client fungieren.
- Der MQTT Broker hingegen ist die zentrale Kommunikationskomponente, welche die gesendeten Nachrichten von Sender zu Empfänger übermittelt.
Mit dieser Architektur entkoppelt MQTT die Clients voneinander, sodass ein Client seine Nachrichten senden kann, selbst wenn empfangende Clients gerade nicht verfügbar sind. Um der Anforderung einer möglichst leichtgewichtigen Client-Implementierung im Internet der Dinge gerecht werden zu können, sind die komplexen Anteile der Nachrichtenübermittlung bei MQTT, welche unter anderem eine gesicherte Nachrichtenübertragung auch bei instabilen Netzwerken garantieren, beim MQTT Broker angesiedelt.
Apache Kafka für das Internet der Dinge
Über die letzten Jahre konnte sich neben MQTT eine weitere Technologie über einen kontinuierlichen Aufstieg freuen: Apache Kafka. Einigen Berichten zufolge ist Apache Kafka inzwischen bei über einem Drittel der Fortune-500-Unternehmen eingesetzt. Grundsätzlich hat sich die Open-Source-Technologie Apache Kafka sowohl bei Enterprise-Organisationen, aber auch kleinen Unternehmen als Real-time-Streaming-Plattform wohl etabliert. Mit seiner verteilten Architektur und seinem Publish-/Subscribe-Protokoll ist es ideal für den Echtzeit-Nachrichtenaustausch zwischen Enterprise-Systemen und -Applikationen auch in hohen Skalierungen geeignet.
Technisch gesehen skaliert Apache Kafka über die Verwendung von sogenannten Partitions pro Topic, um große Nachrichtendurchsätze realisieren zu können. Damit wird der Kafka-Topic-Bereich relativ flach gehalten und die bevorzugte Herangehensweise ist, wenige Topics für die meisten Datenströme zu verwenden. Die Kafka Clients sind eng mit einem Kafka Cluster verbunden, wobei jeder Client die IP-Adressen des Kafka Clusters kennt und direkten Zugang zu allen einzelnen Knoten hat. Innerhalb vertrauenswürdiger Netzwerke ermöglicht diese Architektur eine einfache und schnelle Änderung an der Broker-Topologie. Somit können Topics und Partitions durch die Verwendung mehrerer Knoten direkt von den Kafka Clients aus skaliert werden.
Bei der Betrachtung der Eigenschaften von Apache Kafka lässt sich leicht erkennen, dass es einige Herausforderungen im Internet der Dinge gibt, die für Kafka nicht oder zumindest nicht einfach zu lösen sind. Ein typisches IoT-Projekt hat Millionen von Geräten, die sich über das Internet mit der zentralen Kommunikationsschnittstelle verbinden möchten. IP-Adressen von Infrastrukturkomponenten wie Kafka werden jedoch selten öffentlich im Internet bereitgestellt. Dennoch müssen sich die Kafka Clients mit den Knoten eines Kafka Clusters direkt verbinden können. Im Internet der Dinge werden dazu häufig L4 Load Balancer eingesetzt, die als erste Verteidigungslinie und Proxy zu den dahinterliegenden Enterprise-Applikationen fungieren. Ein direkter Zugriff auf die Kafka-Cluster-Knoten ist bei einem Einsatz von L4 Load Balancern somit nicht mehr möglich.
IoT-Geräte werden normalerweise anhand von Topics segmentiert. Jedes Gerät hat seine eigenen Topics, auf die es Nachrichten schicken und von denen es Nachrichten lesen darf, teilweise mit sehr feingranularen Zugriffsrechten pro Topic. Dies hat zur Folge, dass ein IoT-Projekt oftmals mehrere Millionen IoT Topics nutzt. Da die Skalierung bei Apache Kafka über Partitions der einzelnen Topics funktioniert, sind mehrere Tausend oder sogar Millionen Topics in Kafka eher schwer zu skalieren.
In der Regel handelt es sich bei IoT-Geräten um sehr kleine und eingeschränkte Geräte. Die Implementierung dieser Geräte muss relativ einfach und schlank gehalten werden, um mit Rechenleistung und Speicherkapazität optimal haushalten zu können. Im Gegenzug dazu sind Kafka Clients von ihrem Design her relativ komplex. Sie halten mehrere TCP-Verbindungen zu ihrem Kafka Cluster, sind auf Durchsatz optimiert und wurden nicht mit dem Gedanken an sehr eingeschränkte Hardware konstruiert.
Um ständige Verbindungsabbrüche und erneute Verbindungsaufbauten effizient verarbeiten zu können, braucht es eine Technologie, die damit umgehen kann. Kafka geht in der Regel davon aus, dass die Verbindungen zwischen den Clients und dem Cluster stabil sind und nur gelegentliche Neuverbindungen verarbeitet werden müssen. Für unzuverlässige Netzwerke und gleichzeitige Verbindungsversuche von Millionen von Clients wurde diese Technologie nicht konzipiert.
Fasst man dies alles zusammen, wird deutlich, dass sich Apache Kafka perfekt für die Kommunikation zwischen nativen Cloud-Server-Anwendungen eignet, die in vertrauenswürdigen Netzwerken liegen, stabile IP-Adressen und Verbindungen haben und bei denen die Anzahl der verbundenen Komponenten überschaubar ist. Für die IoT-Gerätekonnektivität ist Kafka jedoch nicht gut geeignet.
IoT Data Streaming mit MQTT und Kafka
Während MQTT und Kafka unterschiedliche Designziele besitzen, entwickeln sie zusammen eine unschlagbare Kombination, bei der beide Technologien ihre Stärken voll ausspielen können: MQTT für Gerätedatenkonnektivität und Kafka für die Übertragung von Echtzeitdaten zwischen Unternehmenssystemen und -anwendungen. Die Frage, die es bei der Planung eines IoT-Projekts zu beachten gilt, ist somit nicht "MQTT vs. Kafka?", sondern "Wie können beide Technologien kombiniert werden, um eine IoT-Ende-zu-Ende-Datenpipeline zu erstellen?".
Um beide Technologien gemeinsam einsetzen zu können, benötigt man eine Verbindung, die es ermöglicht, Nachrichten zwischen beiden Technologien zu transferieren. Dabei spielen Aspekte wie Flexibilität, Skalierung und die Vermeidung von Nachrichtenverlust eine große Rolle. Grundsätzlich gibt es vier verschiedene Architekturansätze, diese Art von Bridge zu realisieren.
1. Kafka Connect for MQTT – Apache Kafka besitzt ein Extension Framework, welches externe Systeme zum Nachrichtenaustausch an das Kafka Cluster anschließen kann. Dieses Framework nennt sich Kafka Connect. Unter den zahlreichen verfügbaren Konnektoren gibt es auch Kafka Connect for MQTT, die einen bidirektionalen Nachrichtenaustausch zwischen einem MQTT Broker und einem Kafka Cluster ermöglichen. Dabei fungiert der Kafka-Konnektor als MQTT Client, der sich auf verschiedene MQTT Topics subscriben kann, um die MQTT-Nachrichten vom MQTT Broker abzuholen und als nativer Kafka Client in das Kafka Cluster zu schreiben. In die andere Richtung agiert der Konnektor ebenfalls als Kafka Client, der Nachrichten aus dem Kafka Cluster liest und als MQTT Client mit dem gewünschten Topic am MQTT Broker published.
Liegt die Kontrolle des MQTT Brokers außerhalb der eigenen Möglichkeiten, ist Kafka Connect for MQTT ein sinnvoller Ansatz um MQTT- Nachrichten zwischen einem MQTT Broker und einem Kafka Cluster zu streamen. Für hohe Skalierungen und Performance ist dieser Ansatz jedoch nicht geeignet. MQTT Client-Bibliotheken, die innerhalb des Kafka-Konnektors verwendet werden, sind in der Regel nicht darauf ausgelegt, riesige Nachrichtenströme zu verarbeiten, sodass es zu Performance- und Skalierungsproblemen kommen kann.
2. MQTT Proxy – Im Gegensatz zum Ansatz mit Kafka-Konnektoren bietet der MQTT Proxy einen Ansatz, der es erlaubt, MQTT-Nachrichten ohne einen MQTT Broker in ein Kafka Cluster zu streamen. Dabei verbinden sich die IoT-Geräte direkt mit der MQTT-Proxy-Applikation, die das Streaming der MQTT-Nachrichten in ein Kafka Cluster übernimmt. Dieser Ansatz ist leicht skalierbar, da die MQTT-Proxy-Applikation stateless ist. Erhöht sich die Anzahl der zu verbindenden Clients, kann die Anzahl der Proxys für ein Kafka Cluster ebenfalls erhöht werden, um die erhöhte Verarbeitungslast auf mehrere Proxys zu verteilen. Der MQTT Proxy implementiert jedoch weder das MQTT Publish/Subscribe Pattern, noch irgendein MQTT Feature, welches zur zuverlässigen Kommunikation im Internet der Dinge notwendig ist. Bezugnehmend auf die MQTT-Spezifikation implementiert der Proxy nur ein kleines Subset der MQTT-Funktionalität und ist somit weder ein vollwertiger MQTT Broker, noch eine standardisierte Lösung. Diesem Ansatz fehlen alle Vorteile, die MQTT für das Internet der Dinge mitbringt. Der MQTT Proxy erstellt eine enge Kopplung eines IoT-Geräts mit dem Kafka Cluster und ermöglicht somit lediglich die Kommunikation zwischen diesem Gerät und Kafka. Eine lose Kopplung zwischen vielen Systemen, wie es bei MQTT eigentlich vorgesehen ist, wird nicht ermöglicht. Dies verhindert, dass beispielsweise einzelne IoT-Geräte untereinander kommunizieren können.
Auch andere wertvolle MQTT Features – wie beispielsweise QoS Level – können nur spärlich von MQTT Proxys realisiert werden. Der Vorteil des QoS Features bei MQTT ist, dass selbst bei einem Verbindungsabbruch Daten nicht verloren gehen, denn der Nachrichtenfluss kann nach erneutem Verbindungsaufbau weitergeführt werden. Dies ermöglichen MQTT Proxys nur dann, wenn der MQTT Client sich mit dem gleichen Proxy wieder verbindet. Bei einem Einsatz von Load Balancern, die eine Least-Connection- oder Round-Robin-Strategie zur Skalierung nutzen, kann dies nicht garantiert werden. Das Vermeiden von Nachrichtenverlust funktioniert somit nur mit stabilen Verbindungen zwischen den MQTT Clients und den MQTT Proxys. Stabile Verbindungen sind jedoch im Internet der Dinge eine unrealistische Annahme.
Dieser Ansatz ist nur dann gut geeignet, wenn Nachrichtenverlust und die Bereitstellung von MQTT Funktionalitäten für eine zuverlässige Kommunikation keine wichtigen Faktoren spielen und eine leichtgewichtige, unidirektionale Alternative zum Streamen von IoT Daten in ein Kafka Cluster gesucht wird.
3. MQTT Custom Bridge – Alternativ zu den beiden oben vorgestellten Möglichkeiten kann auch eine eigene Applikation entwickelt werden. Diese Applikation übernimmt genau auf den Use Case zugeschnitten den Transport von IoT-Daten nach Kafka und leitet Daten aus dem Kafka Cluster an die IoT-Endgeräte weiter. Dabei werden typischerweise Open-Source-MQTT-Client- und Kafka-Client-Bibliotheken verwendet, um eine Brücke zwischen MQTT und Kafka herzustellen.
Die große Herausforderung bei diesem Ansatz liegt darin, die Applikation fehlertolerant und widerstandsfähig zu designen, um beispielsweise mit Verbindungsabbrüchen adäquat umgehen zu können. Wichtig ist, dass ein Nachrichtenverlust beim Übertragen von Daten zwischen MQTT und Kafka vermieden wird. Beispielsweise können Nachrichten verloren gehen, sollte die Custom Bridge den Empfang einer MQTT-Nachricht bereits bestätigt haben und abstürzen, bevor die Nachricht an das Kafka Cluster weitergeleitet werden konnte. Ein kurzzeitig nicht erreichbares Kafka Cluster kann durch Zwischenpuffern der Nachrichten abgefangen werden, die bei einem Absturz der Custom Bridge jedoch ebenfalls verloren wären. Um diese Herausforderungen zu lösen benötigt man Funktionalitäten, die man bereits von MQTT Brokern und Apache Kafka kennt und die mit signifikantem Entwicklungsaufwand verbunden sind.
4. MQTT Broker Extension – Analog zum ersten Ansatz besteht auch die Möglichkeit, dem MQTT Broker mit einer Extension die Möglichkeit zu geben, Nachrichten nach Kafka zu schreiben. Der deutliche Vorteil dieses Ansatzes ist eine tiefe Integration sowohl in den MQTT Broker, als auch zum Kafka Cluster. Somit kann der MQTT Broker als erstklassiger Kafka Client agieren, um Daten von den IoT-Geräten in ein oder sogar mehrere Kafka Cluster zu streamen. Für diesen Ansatz benötigt man jedoch Zugriff auf den MQTT Broker und einen MQTT Broker, der die Möglichkeit besitzt, erweiterbar zu sein. Manche MQTT Broker bieten auch eine derartige Erweiterung in ihrem Portfolio an, sodass keine eigenständige Entwicklung stattfinden muss.
Durch die tiefe Integration in den MQTT Broker können bei dieser Variante alle MQTT-Funktionalitäten angeboten werden. Die in Kafka Records übersetzten MQTT-Nachrichten werden vom inkludierten, nativen Kafka Client in das Kafka Cluster weitergeleitet. Auf diese Weise können die IoT- Gerätedaten zu einem oder mehreren Kafka Clustern weitergeleitet werden und gleichzeitig auch andere Applikationen auf die Daten zugreifen. Auch die Kommunikation zwischen den IoT-Geräten ist durch die lose Kopplung über den MQTT Broker weiterhin problemlos möglich. MQTT Broker, die Funktionalitäten wie Hochverfügbarkeit, Persistenz, Performance und Widerstandsfähigkeit aufweisen, können die Nachrichten zwischenpuffern, um einen Nachrichtenverlust zu vermeiden, sollte auf das Kafka Cluster gerade nicht geschrieben werden können. Dieser Ansatz liefert Ende-zu-Ende-Nachrichtenzustellungsgarantien auch für unzuverlässige Netzwerke, öffentliche Internetkommunikation und wechselnde Netzwerktopologien, wie beispielsweise häufig zu beobachten mit Kubernetes.
Fazit
In einer Welt, in der bereits jetzt mehr Dinge vernetzt sind, als sich Menschen über das Internet vernetzen und in der diese Zahl über die nächsten Jahre exponentiell ansteigen wird, braucht es gute Konzepte, um die von den Geräten erstellten Daten in Systeme zu übertragen, die diese Daten weiterverarbeiten. MQTT hat sich als das De-facto-Standardprotokoll für das Internet der Dinge herauskristallisiert, mit dem sich IoT-Geräte über unzuverlässige Netzwerke und in hohen Skalierungen zum sofortigen Nachrichtenaustausch verbinden können. Apache Kafka auf der anderen Seite zeigt seine Stärken in der systemübergreifenden Echtzeitkommunikation von Enterprise-Applikationen bei hohen Skalierungen. Die Herausforderung besteht darin, die Datenströme von MQTT nach Kafka zu bringen, um von dort aus in anderen Systemen weiterverarbeitet werden zu können. Für den Übergang zwischen MQTT und Kafka gibt es mehrere Möglichkeiten, die mit Vor- und Nachteilen erscheinen. Die für die meisten Anwendungsfälle wohl am besten geeignete Lösung ist die MQTT Broker Extension, die eine tiefe Integration sowohl in MQTT als auch in Kafka bietet. Mit dieser Lösung stehen alle Funktionalitäten beider Protokolle zur Verfügung, die in ihrer jeweiligen Domain ihre Stärken voll ausnutzen können. Zudem bietet sie aktuell den besten Ansatz bidirektionale Nachrichtenströme von Millionen von IoT-Geräten in Echtzeit und ohne Nachrichtenverlust zu streamen.