© GreenFlash/Shutterstock.com
Teil 1: Einführung in die Nachrichtenverarbeitung mit Spring Kafka

Frühlingsbotschaften


Apache Kafka erfreut sich als Messaging-Middleware immer größerer Beliebtheit und Verbreitung in der Entwicklercommunity. Dem trägt jetzt auch Spring Rechnung und bietet mit Spring Kafka eine sehr einfache Möglichkeit, Kafka in eine Spring-basierte Applikation zu integrieren. Zum Auftakt der Artikelserie möchten wir anhand praktischer Beispiele zeigen, wie Spring Kafka für die Entwicklung eventgestützter Microservices verwendet werden kann.

Video: Microservices mit Spring Boot, Angular 2 und Docker

Ursprünglich von LinkedIn 2011 entwickelt und veröffentlicht [1], [2], hat sich Kafka seitdem nicht nur zu einem Apache-Projekt [3], sondern auch zu einem der interessantesten Frameworks für Stream Processing und Message Brokering entwickelt. Bei Kafka handelt es sich um ein verteiltes Messagingsystem, das sich der klassischen Producer- und Consumer-Semantik bedient (Abb. 1) und den Anspruch hat, vor allen Dingen schnell, skalierbar und robust zu sein. Um diesen Anspruch zu erfüllen, besitzt Kafka besondere Eigenschaften, die wir in diesem Artikel näher vorstellen werden.

guenther_1.tif_fmt1.jpgAbb. 1: Überblick über die Systeme eines Kafka-Clusters

Das Bindeglied zwischen Producer und Consumer und somit das Herzstück von Kafka ist der Broker. Er pflegt von einem Producer generierte Nachrichten – nach Topics gruppiert – in einer verteilten und replizierten Append-only-Datenstruktur, dem Commit Log. Datensätze sind hierbei aus Sicht von Kafka als simple Byte-Arrays zu verstehen. Außer einer pro Partition eindeutigen, sequenziellen ID, auch als Offset bezeichnet, werden keine Metadaten auf Nachrichtenebene verwaltet. Eine neu eingeführte Ausnahme hierfür ist der transaktionale Modus, der mit Kafka 0.11 vorgestellt wurde. Dadurch grenzt sich Kafka nicht nur von anderen Messaginglösungen wie z. B. RabbitMQ ab, sondern erfüllt auch das Kriterium der Effizienz. Salopp gesagt ließe sich Kafka auch als ein verteiltes Dateisystem mit Spezialisierung auf die effiziente Verwaltung eines Commit Logs beschreiben.

Der fachlichen Gruppierung von Nachrichten nach Topics steht eine technische Sortierung nach Partition zur Seite, um sowohl der Skalierbarkeit als auch der Robustheit gerecht zu werden. Die Anzahl der Partitionen und deren Replikationsfaktor sind auf Topic-Ebene konfigurierbar, was eine Abwägung von Datendurchsatz gegen Datensicherheit erlaubt. Bei einem Replikationsfaktor größer eins wird ein Broker als Leader für eine Partition definiert. Die Auswahl eines Leaders und die Überwachung des Zustands aller Broker geschehen mithilfe von Apache ZooKeeper [4], worauf wir im Rahmen dieses Artikels jedoch nicht näher eingehen werden.

Die Zuordnung einer Nachricht zu einer Partition kann auf zwei Wegen erfolgen: Im ersten Fall besitzt die von einem Producer emittierte Nachricht einen fachlichen Schlüssel (Keyed Message), dann erfolgt die Zuordnung auf eine Partition als Standard nach dem Schema hashCode() % numbersOfPartitions. Nachrichten mit identischem Schlüssel landen somit immer auf derselben Partition, was – kombiniert mit der Ordnungsgarantie pro Partition – den Charme besitzt, dass zusammengehörige Nachrichten zeitlich sortiert auf derselben Partition liegen (Abb. 2). Sollte kein Schlüssel existieren, fällt Kafka auf eine Round-Robin-Zuordnung der Nachrichten auf die Partitionen zurück. Erwähnenswert ist noch, dass Kafka sich über ZooKeeper auf Consumer-Gruppenebene merkt, welche Offsets in welcher Partition zuletzt gelesen bzw. bestätigt wurden, allerdings gelesene Nachrichten nicht entfernt. Ob und in welchem Intervall und nach welcher Strategie Nachrichten entfernt bzw. Commit Logs kompaktiert werden, lässt sich ebenfalls auf Topic-Ebene konfigurieren.

guenther_2.tif_fmt1.jpgAbb. 2: Nachrichtenfluss innerhalb eines Topics

Producer und Consumer lernen sich nie kennen

Producer und Consumer sind die Clients in einer Kafka-Systemlandschaft, die keine Kenntnis voneinander besitzen, sondern Topic-fokussiert mit dem Broker produzierend bzw. konsumierend Nachrichten austauschen. Für das Emittieren einer Nachricht ist der Producer zuständig. Ein Producer kann für ein oder mehrere Topics Nachrichten an den Cluster übermitteln und über das Setzen des bereits beschriebenen Schlüssels sicherstellen, dass fachlich zusammengehörende Nachrichten in derselben Partition abgelegt werden. Intern besitzt der Producer einen Buffer für noch nicht gesendete Nachrichten, die an den Kafka-Cluster gesendet werden sollen. Die Übertragung erfolgt asynchron und der Empfang wird vom Cluster anhand konfigurierbarer Kriterien bestätigt. Erst nach Erhalt dieser Bestätigung gilt eine Nachricht als erfolgreich übermittelt. Auf der verarbeitenden Seite der Nachrichtenkette stehen die Consumer, die in Consumer-Gruppen organisiert Topics abonnieren. Eine Consumer-Gruppe liest in ihrer Gesamtheit alle Partitionen eines Topics, jedoch kann eine Partition maximal von einem Consumer gelesen werden, was sicherstellt, dass innerhalb einer Consumer-Gruppe eine Nachricht nicht mehrfach verarbeitet wird. Es ist dennoch durchaus möglich, mehr Consumer als Partitionen in einer Gruppe zu haben. Sollte in diesem Fall ein Consumer ausfallen, wird einem bis dahin arbeitslosen Consumer die entsprechende Partition zugewiesen.

Das Lesen einer Nachricht aus einem Topic erfolgt immer anhand eines Nachrichten-Offsets. Bei einem Poll vom Cluster wird der zuletzt verarbeitete Nachrichten-Offset übergeben und im Gegenzug werden dem Consumer alle Nachrichten (maximale Batchgrößen sind ebenfalls konfigurierbar) übermittelt, die einen höheren Offset besitzen als der übergebene. Das Bestätigen des zuletzt erfolgreich verarbeiteten Offsets obliegt dem Consumer. Dies geschieht nach einem erfolgreichen Polling entweder über einen Auto-Commit oder kann auch explizit programmatisch erfolgen.

Nach diesem groben Abriss über die Architektur und Funktionsweise von Apache Kafka werden wir als Nächstes auf die von Spring Kafka [5] bereitgestellten Hilfsmittel eingehen, um dann an praktischen Beispielen zu demonstrieren, wie sich eine einfache Nachrichtenkette mit Spring Kafka aufsetzen lässt.

Nachrichten schreiben

Nachrichten stellt der Entwickler in Spring Kafka über einen Kafka-eigenen Producer<K,V> in ein dediziertes Topic ein. Eine Instanz von Producer ist typparametrierbar: K repräsentiert hie...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang