MQTT trifft Pulsar: Eine pragmatische Bridge für moderne IoT-Architekturen

MQTT trifft Pulsar: Eine pragmatische Bridge für moderne IoT-Architekturen
By Matthias Petermann / on 27.11.2025

Vom Gerät ins Event-Backbone

In vielen IoT-Landschaften stößt man auf eine vertraute Ausgangslage: Unzählige Sensoren und Edge-Geräte sprechen MQTT – schlank, einfach, effizient. Dazu kommen gewachsene Infrastrukturen mit etablierten Brokern wie Mosquitto, EMQX, HiveMQ oder den MQTT-Stacks diverser Industrie- und Gateway-Hersteller. Diese Broker sind tief in bestehende Edge-Topologien integriert, oft hochverfügbar betrieben und Bestandteil sicherheitskritischer Kommunikationspfade.

Gleichzeitig entsteht im Backend zunehmend der Wunsch nach Streaming, Persistenz, Skalierung, Rückverfolgbarkeit, Multi-Tenancy und modernen Auswertungsmöglichkeiten – etwas, das klassische MQTT-Broker nur teilweise oder gar nicht leisten können.

Die Frage liegt daher nahe:

Warum nicht MQTT-Nachrichten direkt in Apache Pulsar streamen – ohne die bestehende MQTT-Infrastruktur umzubauen?

Genau aus diesem Gedanken entstand pulsar-iotbridge: Ein kompaktes Go-Tool, das sich an einen bestehenden MQTT-Broker anhängt, dessen Topics abonniert und alle eingehenden Nachrichten in eine saubere, konsistente Pulsar-Namensstruktur spiegelt.

So bleibt die vorhandene MQTT-Landschaft unverändert, während im Backend ein modernes, skalierbares Event-System entsteht.


Motivation

MQTT ist hervorragend für Gerätekommunikation geeignet, aber nur bedingt für Backend-Verarbeitung und Analyse. Dagegen bietet Apache Pulsar:

  • Topics mit Aufbewahrung (Retention)
  • horizontale Skalierung
  • Subskriptionsmodelle für Echtzeit und Replays
  • ein sauberes Multi-Tenant-Modell
  • Backlogs, DLQs, Compaction, Geo-Replikation …

Kurz: MQTT für die Edge, Pulsar für das Backend – zwei Welten, die sich optimal ergänzen.

ℹ️ Warum nicht direkt Pulsar auf den Geräten?

Pulsar ist für große Streaming-Workloads optimiert, nicht für stromsparende Edge-Devices. MQTT hingegen ist für kleine Geräte gemacht, unterstützt QoS, ist bandbreitenschonend und leichtgewichtig.

Die Kombination aus beidem bietet das Beste aus zwei Welten.


Idee

Die Grundidee von pulsar-iotbridge ist bewusst minimalistisch:

  1. Mit einem MQTT-Broker verbinden
  2. Alle gewünschten Topics abonnieren (standardmäßig: #)
  3. Jede eingehende Nachricht einer Namensstruktur zuordnen
  4. Das Payload unverändert im zugehörigen Pulsar-Topic veröffentlichen

Aus einem MQTT-Topic wie:

dt/device123/temperature

wird ein Pulsar-Topic wie:

persistent://public/mqtt_ingest/dt/device123/temperature

Ohne Transformation, ohne Magie – einfach ein Event-Transport zwischen zwei Welten.

📝 Was die Bridge nicht tut
  • keine semantische Interpretation
  • keine Datenanreicherung
  • keine Schemas
  • keine Transformationen

Sie ist bewusst „stupid simple“. Genau das macht sie robust.


Umsetzung

Der Fokus des Projekts liegt nicht auf möglichst vielen Features, sondern auf einer nachvollziehbaren, wartbaren und sicheren Architektur.

Pulsar-iotbridge setzt auf zwei bewährte Bausteine:

1. MQTT-Client (Paho)

Die Bridge nutzt die etablierte Go-Implementation von Eclipse Paho für MQTT. Sie verbindet sich als Client, abonniert die gewünschten Topics und erhält jede Nachricht über einen Callback.

2. Apache Pulsar Go-Client

Für das Backend nutzt die Bridge den nativen Pulsar-Go-Client. Dieser bietet:

  • effizientes Batching
  • LZ4-Kompression
  • asynchrones Publishing
  • stabile Verbindungshandhabung

Ein Publisher wird pro Pulsar-Topic erzeugt und wiederverwendet. Damit entsteht ein klar definierter Pfad pro Topic – strukturiert und sauber isoliert.

ℹ️ Warum Go?

Go eignet sich hervorragend für IO-intensive Tools:

  • kleine, statische Binaries
  • schnelle Startup-Zeiten
  • sehr gute Parallelisierung
  • geringer Memory-Footprint

Ideal für leichtgewichtige Integrationskomponenten.


Architektur aus der Vogelperspektive

[ IoT-Device ] --MQTT--> [ MQTT-Broker ] --> [ pulsar-iotbridge ]
                                                          |
                                                          | Pulsar-Event
                                                          v
                                                [ Apache Pulsar ]
                                                          |
                                                          v
                                               [ Analytics / Backend ]
ℹ️ Lose Kopplung durch Events
Die Geräte wissen nichts von Pulsar. Die Backend-Anwendungen wissen nichts von MQTT. Die Bridge vermittelt neutral zwischen den Welten – sauber und wartungsarm.

Lokaler Test mit Podman

Mit wenigen Zeilen lässt sich ein Pulsar-Standalone starten:

podman run -it --rm \
  -p 6650:6650 \
  -p 8080:8080 \
  docker.io/apachepulsar/pulsar:4.0.7 \
  bin/pulsar standalone

Parallel dazu kann ein MQTT-Broker laufen, z. B. Mosquitto.


Starten der Bridge

./pulsar-iotbridge run \
  --mqtt-url tcp://localhost:1883 \
  --pulsar-url pulsar://localhost:6650 \
  --tenant public \
  --namespace mqtt_ingest \
  --workers 8

Nun werden alle MQTT-Nachrichten aus allen Topics abgefangen und nach Pulsar gespiegelt.

💡 Prometheus-Metriken eingebaut

pulsar-iotbridge bringt von Haus aus einen kleinen Prometheus-Endpoint (/metrics) mit. Damit lassen sich zentrale Betriebsgrößen direkt überwachen – ohne zusätzliche Instrumentierung.

Erfasst werden u. a.:

  • eingehende MQTT-Nachrichten pro Topic
  • erfolgreich veröffentlichte Pulsar-Nachrichten
  • ausstehende (pending) Pulsar-Publishes
  • Fehlerzähler pro Pulsar-Topic
  • gedroppte Nachrichten bei Überlast

So behält man jederzeit im Blick, ob die Bridge unter Last sauber arbeitet, ob Topics „heiß laufen“ oder ob Eingangs-Queues an ihre Grenzen kommen. Ideal für Dashboards, Alerting und Capacity-Planung.


Verifizieren

Empfangsseite in Pulsar:

./pulsar-cli consumer --regex -t 'persistent://public/mqtt_ingest/.*' -s debug

MQTT-Test:

mosquitto_pub -t dt/dev1/temp -m "22.4"

Wenige Millisekunden später taucht die Nachricht im Pulsar-Consumer auf.


Warnhinweise und Limitationen

⚠️ Wichtig: Keine garantierte Nachrichtenreihenfolge

Durch den Worker-Pool und asynchrones Publishing kann die Reihenfolge von Nachrichten eines MQTT-Topics im Pulsar-Topic abweichen.

Wer strikte Ordering-Semantik benötigt, sollte:

  • die Bridge mit --workers 1 betreiben, oder
  • einen Serialisierungsmechanismus pro Topic einführen, oder
  • direkt Pulsar-IO bzw. andere integrierte Mechanismen nutzen.
⚠️ Smile-but-drop bei Überlast

Die Eingangsqueue ist bewusst begrenzt. Ist sie voll, werden Nachrichten verworfen, statt Backpressure auf die Geräte auszuüben.

Das schützt die Stabilität des Gesamtsystems – aber nicht jede Anwendung toleriert Drops.


Alternative: Pulsar-MOP (MQTT-on-Pulsar)

Statt eine externe Bridge zu betreiben, erweitert Pulsar-MOP den Pulsar-Broker selbst um einen vollständigen MQTT-Server. Geräte sprechen weiterhin MQTT — landen aber direkt im Pulsar-Ökosystem.

Vorteile:

  • keine separate Bridge oder zusätzliche Infrastruktur notwendig
  • Geräte senden direkt an Pulsar → kein Medienbruch
  • vollständige native MQTT-Kompatibilität (QoS, Sessions, Retain etc.)
  • Daten landen sofort in Pulsar-Topics und profitieren von Retention, Backlog & Replays

Nachteile:

  • ersetzt den bestehenden MQTT-Broker vollständig
  • höherer operativer Footprint (Pulsar muss auch MQTT-Workloads stemmen)
  • für ressourcenbeschränkte Edge-Szenarien oft zu schwergewichtig
  • weniger entkoppelt als eine externe Bridge (Monolithisierungstendenz)
ℹ️ Pulsar-MOP (MQTT-on-Pulsar)

Projektseite: https://github.com/streamnative/mop

Pulsar-MOP erweitert den Pulsar-Broker um einen vollständig integrierten MQTT-Server: Geräte sprechen weiterhin MQTT – die Nachrichten landen jedoch direkt in Pulsar.


Fazit

pulsar-iotbridge ist ein kleines, aber wirkungsvolles Werkzeug, um bestehende MQTT-Landschaften in die Ereigniswelt von Apache Pulsar zu heben – ohne Geräte umzubauen, ohne große Architekturveränderungen, ohne schwergewichtige Connector-Infrastruktur.

📝 Proof statt PowerPoint

pulsar-iotbridge ist bewusst als Proof of Concept umgesetzt: einfach, nachvollziehbar, ohne unnötige Magie – und mit klar sichtbaren Grenzen.

Der Fokus liegt auf Verständlichkeit, nicht auf Vollständigkeit. Aktuelle Limitationen sind u. a.:

  • keine garantierte Nachrichtenreihenfolge (parallelisierte Worker, async Publish)
  • Smile-but-drop-Verhalten bei Überlast statt Backpressure
  • keine Schema-Unterstützung, keine Transformationen
  • kein Zero-Copy-Pfad und bewusst minimalistische Fehlerbehandlung

Trotzdem: Der Code läuft, ist transparent und zeigt den Ansatz auf praktische Weise.


Bildnachweis: Das Pulsar-Logo ist eine eingetragene Marke der Apache Software Foundation. Verwendung im Rahmen redaktioneller Berichterstattung gemäß den offiziellen Richtlinien.