Zum Hauptinhalt springen

Apache Kafka Treiber

Der Apache Kafka Treiber von PlantPulse Edge ist eine Java-Implementierung, die die kafka-clients 4.1.2 Bibliothek kapselt. Er abonniert als Consumer Topics einer externen Streaming-Plattform (Apache Kafka / Confluent Cloud / AWS MSK / Azure Event Hubs Kafka API), hält die Records in einem In-Memory-Cache und gibt den Cache-Wert im Polling-Zyklus jedes Tags zurück. Schreiben erfolgt über producer.send (asynchron).

Quelle: plantpulse.driver.protocol.kafka.*

KlasseVerantwortung
KafkaDriverProtocolDriver Implementierung — connect/read/write/close, Topic-Cache, lazy subscribe, Hintergrund-Poller-Thread

Bibliothek: lib/kafka-clients-4.1.2.jar


Unterschied zu MQTT / WebSocket​

PlantPulse bietet drei message-basierte Treiber — alle gemeinsam nutzen denselben JsonExtract 4-Modus-JSON-Decoder.

TreiberWire-ProtokollPayloadEinsatzbereich
MQTT_CLIENTMQTT v3.1.1beliebig (meist JSON/Klartext)IIoT-Broker (HiveMQ / Mosquitto / EMQX), QoS 0/1/2
WEBSOCKETws/wssbeliebig (meist JSON)Streaming-Server / proprietäre Push-API
KAFKA (diese Seite)Kafka-Wire-ProtokollRecord-Key/Value (meist JSON-String)High-Throughput-Streaming, Replay (Offset), Consumer-Group
SPARKPLUG_BMQTT + ProtobufSparkplug-B-PayloadCirrus Link / Tahu / Ignition Standard (IIoT-Spec über MQTT)

Bei Kafka stehen persistentes Log + Offset-Replay im Mittelpunkt — ein neuer Consumer, der sich mit auto-offset=earliest registriert, kann Daten ab dem letzten Stand erhalten (innerhalb der Retention des Brokers).


Ablauf​

broker ──ConsumerRecord──> KafkaConsumer.poll() ──> pollerLoop (background thread)
│
├─ rawByTopic.put(topic, value)
└─ JsonExtract.updateCache(topicCache, topic, value)

PlantPulse 폴러 ──read(addr)──> JsonExtract.parse(addr.address) ──> JsonExtract.extract(...) (in-memory hit)
write(addr, value) ──KafkaProducer.send(ProducerRecord(topic, value))──> broker

Beim ersten read-Aufruf ergibt ein Cache-Miss ein lazy subscribe (Aufruf consumer.subscribe(...)) und Rückgabe eines leeren Strings — ab dem nächsten Zyklus liegen echte Werte vor. Topics, die in tag_map registriert sind, werden direkt nach dem Verbindungsaufbau über preSubscribeFromTagMap() gesammelt abonniert, sodass Werte bereits im ersten Zyklus ankommen können.


4-Modus-JSON-Dekodierspezifikation​

Das JsonExtract-Hilfsprogramm vereinheitlicht die Nachrichtendekodierung der drei Treiber MQTT / WebSocket / Kafka.

ModusAdressformatVerhalten
SCALAR<topic> oder <topic>.valuegesamte Nachricht als String. Bei JSON-Objekt: Rohdaten-Fallback.
KEY<topic>:<json-key>Wert eines Schlüssels im Top-Level-JSON-Objekt
PATH<topic>:$.<json-path>dynamische Auswertung per JSON Pointer (z. B. $.data.tags.T1 → /data/tags/T1)
RAW<topic>:_raw_letzte Rohdaten-Nachricht (Debugging)

Cache-Struktur — verwendet einen einzigen Map<String, String>, Schlüssel ist topic + "|" + field:

SchlüsselBedeutung
topic|_raw_letzte Rohdaten-Nachricht
topic|valueSkalar (nur bei nicht-JSON-Nachricht)
topic|<json-key>Werte je Top-Level-JSON-Schlüssel (nur bei Objekt)

Der PATH-Modus umgeht den Cache und wertet die letzte Rohdaten-Nachricht aus rawByTopic bei jedem Aufruf mit JSONPointer.queryFrom(...) aus.


Optionen​

SchlüsselStandardBeschreibung
group-idplantpulse-edge-<opc_id>Consumer-Gruppen-ID. Einheit für Offset-Commit.
security-protocolPLAINTEXTPLAINTEXT / SSL / SASL_PLAINTEXT / SASL_SSL
sasl-mechanism(keine)PLAIN / SCRAM-SHA-256 / SCRAM-SHA-512
sasl-jaas-config(keine)JAAS-Konfiguration (z. B. ...PlainLoginModule required username="u" password="p";)
auto-offsetlatestearliest / latest — Startpunkt einer neuen Gruppe

enable.auto.commit=true ist stets gesetzt, sodass der Broker Offsets automatisch committet (Standard: 5-Sekunden-Intervall).


Verbindungslebenszyklus​

MethodeAktion
connect()Optionen anwenden → Consumer/Producer erzeugen → Poller-Thread starten → tag_map gesammelt abonnieren
pollerLoop()consumer.poll(500ms) wiederholen → je Record JsonExtract.updateCache(...)
read()Parsen → bei Cache-Miss lazy subscribe → bei Cache-Hit Wert zurückgeben
write()producer.send(new ProducerRecord<>(topic, value)) (asynchron)
close()consumer.wakeup() → Thread-Join → Consumer/Producer schließen → Cache leeren

Grenzen und zukünftige Arbeiten​

  • Wiederverbindung — kafka-clients besitzt eine eigene Reconnect-Logik; wenn jedoch der gesamte Broker ausfällt und langjährige poll() fehlschlagen, markiert der Treiber setConnected(false) nicht separat → für Betriebsstatus-Monitoring werden Broker-seitige Metriken empfohlen.
  • AWS MSK IAM — aws-msk-iam-auth-JAR erforderlich (derzeit nicht enthalten). Später aws-msk-iam-auth-1.x.jar in lib/ aufnehmen und sasl.client.callback.handler.class als Option freigeben.
  • TLS-Truststore — nicht über Treiberoptionen konfigurierbar; es wird der JVM-System-Truststore verwendet. Bei einem Broker mit selbstsignierter privater CA das CA-Zertifikat in den JVM-Truststore aufnehmen oder der Gateway-Startoption -Djavax.net.ssl.trustStore=… hinzufügen.
  • Producer mit partition/key-Angabe — Write erfolgt immer ohne Key, sodass die Partition per Round-Robin bestimmt wird. Das bedeutet: Schreibvorgänge desselben Tags kommen nicht garantiert in Reihenfolge an. Ist eine partitionäre Reihenfolge erforderlich, das Topic mit einer Partition anlegen oder die Reihenfolge auf Consumer-Seite sicherstellen.
  • Transaktionaler Producer — nicht unterstützt. Ein idempotenter Producer wird derzeit ebenfalls nicht explizit aktiviert.

Testorte​

test/java/plantpulse/driver/protocol/kafka/KafkaDriverTest.java — 18 Tests.

  • Klassenladung / Hierarchie (BaseProtocolDriver / ProtocolDriver)
  • Anfangszustand / Metadaten (isConnected/isWriteSupported/isExternal/getDriverSource)
  • Nicht verbundener Zugriff: read/write/null sicher
  • getDebugBaseUrl — kafka://, Standard-Port (9092)
  • Optionsparsing — group-id / security-protocol / sasl-* / auto-offset, options=null sicher
  • 4-Modus-Dekodierung — Cache direkt befüllt, KEY / PATH / RAW / SCALAR / .value-Suffix werden alle verifiziert
  • close() nicht verbunden sicher

test/java/plantpulse/driver/protocol/common/JsonExtractTest.java — 23 Tests (integrierte Verifikation von 4-Modus-Parser/Cache/Extraktion).

Integrationstests mit echtem Broker sind separat — diese Unit-Tests laufen ohne externes Kafka.