37 Minimaler Einstieg in Kafka Streams – nur zur Einordnung

Während die bisherigen Kapitel Event-Verarbeitung durch explizite Producer und Consumer behandelt haben, existiert eine weitere Kategorie von Tools: Stream Processing Frameworks. Kafka Streams ist ein prominenter Vertreter dieser Kategorie und bietet eine alternative Sichtweise auf Event-Verarbeitung. Das Verständnis dieser Paradigmen hilft dabei, die richtige Technologie für spezifische Anwendungsfälle zu wählen.

37.1 Stream Processing Paradigmen

Stream Processing betrachtet Events nicht als diskrete Nachrichten, die einzeln verarbeitet werden, sondern als kontinuierliche Datenströme, die durch Verarbeitungs-Pipelines fließen. Diese Sichtweise ändert fundamental, wie über Event-Verarbeitung gedacht wird.

Traditional Event Processing behandelt jedes Event einzeln. Ein Consumer erhält ein Event, verarbeitet es vollständig und geht zum nächsten über. Dies entspricht dem “Pull-and-Process”-Pattern, das wir in den vorherigen Kapiteln verwendet haben. Der Consumer kontrolliert das Tempo der Verarbeitung.

Stream Processing denkt in kontinuierlichen Transformationen. Events fließen durch eine Kette von Operationen, wobei jede Operation eine spezifische Transformation durchführt. Das Tempo wird durch den Stream selbst bestimmt, nicht durch einzelne Verarbeitungsschritte.

Ein typisches Beispiel verdeutlicht den Unterschied: Ein E-Commerce-System soll aus Bestellungen in Echtzeit Umsatzstatistiken berechnen.

Mit Traditional Processing würde ein Consumer jede Bestellung einzeln empfangen, den aktuellen Tagesumsatz aus einer Datenbank laden, den Bestellwert hinzuaddieren und das Ergebnis zurückschreiben. Jede Bestellung ist ein separater Verarbeitungsvorgang.

Mit Stream Processing definiert man eine Pipeline: Bestellungen → Filterung gültiger Bestellungen → Extraktion des Bestellwerts → Aggregation nach Tag → Ausgabe der Tagesumsätze. Diese Pipeline läuft kontinuierlich und verarbeitet automatisch alle eingehenden Events.

Paradigma Kontrolle Zustandsmanagement Skalierung Anwendungsfall
Event Processing Pull-basiert Explizit Manual Komplexe Geschäftslogik
Stream Processing Push-basiert Framework-managed Automatisch Real-time Analytics

Deklarative vs. Imperative Programmierung ist ein weiterer Unterschied. Traditional Event Processing ist imperativ: “Hole Event, prüfe Bedingung, führe Aktion aus, speichere Ergebnis.” Stream Processing ist deklarativ: “Transformiere Bestellungen zu Umsatzstatistiken durch Filterung, Extraktion und Aggregation.”

Pipeline-Denken verändert die Architektur grundlegend. Anstatt einzelner Services, die Events empfangen und verarbeiten, entstehen Verarbeitungs-Topologien mit mehreren Stufen. Jede Stufe hat eine spezifische Verantwortung und kann unabhängig skaliert werden.

Real-Time vs. Batch wird in Stream Processing natürlich adressiert. Die gleiche Pipeline kann sowohl historische Events (Batch) als auch Live-Events (Stream) verarbeiten. Der Code bleibt identisch, nur die Datenquelle ändert sich.

37.2 Stateful Stream Processing

Die Kombination von Stream Processing mit Zustandsmanagement eröffnet mächtige Möglichkeiten, die mit stateless Streams nicht erreichbar sind. Stateful Stream Processing ermöglicht komplexe Aggregationen, Join-Operationen und zeitbasierte Berechnungen.

Windowing ist das fundamentale Konzept für zeitbasierte Stateful Processing. Events werden in zeitliche Fenster gruppiert, und Berechnungen werden pro Fenster durchgeführt. Ein 15-Minuten-Fenster würde alle Events der letzten 15 Minuten für Berechnungen verwenden.

Tumbling Windows haben feste, nicht-überlappende Zeiträume. Jedes Event gehört zu genau einem Fenster. Dies eignet sich für periodische Berichte: stündliche Umsätze, tägliche Nutzerstatistiken.

Sliding Windows überlappen sich und werden kontinuierlich aktualisiert. Ein 1-Stunden-Sliding-Window, das alle 5 Minuten aktualisiert wird, zeigt immer die Statistiken der letzten Stunde. Dies eignet sich für Real-Time-Dashboards.

Session Windows gruppieren Events basierend auf Aktivitätspausen. Alle Events eines Nutzers werden zu einer Session zusammengefasst, bis eine Pause von z.B. 30 Minuten auftritt. Dies eignet sich für Benutzerverhalten-Analysen.

Window-Typ Überlappung Aktualisierung Anwendungsfall
Tumbling Nein Periodisch Berichte, Batch-Analytics
Sliding Ja Kontinuierlich Real-Time Dashboards
Session Variable Bei Aktivität User Behavior Analysis

Join-Operationen zwischen Streams ermöglichen komplexe Korrelationen. Ein Order-Stream kann mit einem Customer-Stream gejoint werden, um Bestellungen mit Kundendaten anzureichern. Dies ersetzt traditionelle Database-Lookups durch Stream-basierte Operationen.

Aggregations sammeln Daten über Zeit oder Gruppierungen. Count, Sum, Average, Min, Max sind Standardoperationen. Komplexere Aggregationen wie Top-K oder Distinct-Count sind ebenfalls möglich.

State Stores verwalten den Zustand von Aggregationen und Joins automatisch. Das Framework kümmert sich um Partitionierung, Replikation und Recovery des Zustands. Entwickler müssen sich nicht um State-Management-Details kümmern.

Exactly-Once Semantik wird vom Framework garantiert, ohne dass Entwickler explizit Idempotenz implementieren müssen. Dies vereinfacht die Entwicklung von kritischen Stream Processing Anwendungen erheblich.

37.3 Topology Design

Stream Processing Anwendungen werden als Topologien modelliert - gerichtete Graphen von Verarbeitungsknoten. Das Design dieser Topologien bestimmt die Performance, Skalierbarkeit und Wartbarkeit der Anwendung.

Source-Processor-Sink Pattern ist die grundlegende Struktur. Sources lesen Events aus Topics, Processors transformieren Events, Sinks schreiben Ergebnisse zurück. Jeder Knoten hat eine spezifische Verantwortung.

Linear Topologies verarbeiten Events in einer geraden Linie: Input → Transform → Filter → Output. Dies entspricht funktionaler Programmierung und ist einfach zu verstehen und zu testen.

Branching Topologies splitten einen Stream in mehrere Pfade. Ein Order-Stream könnte in separate Streams für verschiedene Produktkategorien aufgeteilt werden. Jeder Branch kann unterschiedlich verarbeitet werden.

Joining Topologies kombinieren mehrere Streams. Customer-Events und Order-Events können gejoint werden, um eine vollständige Sicht auf Kundenaktivitäten zu erhalten.

// Konzeptionelle Topology für E-Commerce Analytics
Orders Topic → Filter Valid Orders → Extract Values → Aggregate by Hour → Revenue Topic
     ↓                                                        ↑
Customer Topic → Filter Premium Customers ────────────────────┘

Sub-Topologies ermöglichen Modularisierung komplexer Verarbeitungslogik. Ähnlich wie Microservices können verschiedene Sub-Topologies unabhängig entwickelt und deployed werden.

Parallelisierung erfolgt automatisch basierend auf der Partitionierung der Input-Topics. Jede Partition wird von einer separaten Task verarbeitet, was natürliche Skalierung ermöglicht.

Co-Partitioning ist notwendig für Join-Operationen. Streams, die gejoint werden sollen, müssen nach demselben Key partitioniert sein. Dies stellt sicher, dass zusammengehörige Events auf derselben Task verarbeitet werden.

Stateful vs. Stateless Operationen haben unterschiedliche Skalierungs-Charakteristiken. Stateless Operationen (map, filter) skalieren linear. Stateful Operationen (aggregate, join) erfordern State-Redistribution bei Skalierung.

Error Handling in Topologies ist anders als in Traditional Processing. Fehler in einem Processor können die gesamte Topology stoppen. Deserialization-Fehler, Processing-Exceptions und Timeout-Probleme müssen architekturell adressiert werden.

Testing von Topologies nutzt spezielle Test-Frameworks. Topology-Tests sind integration-artig: Input-Events werden eingespeist, und Output-Events werden validiert. Dies ist anders als Unit-Tests einzelner Event-Handler.

Deployment und Operationen von Stream Processing Anwendungen haben eigene Charakteristika. State Stores müssen beim Deployment berücksichtigt werden. Rolling Updates erfordern sorgfältige Planung, um State nicht zu verlieren.

Stream Processing mit Tools wie Kafka Streams bietet mächtige Abstraktionen für komplexe Event-Verarbeitung. Es eignet sich besonders für Anwendungsfälle mit kontinuierlichen Transformationen, Real-Time Analytics und komplexen zeitbasierten Berechnungen. Die Entscheidung zwischen Traditional Event Processing und Stream Processing sollte basierend auf den spezifischen Anforderungen getroffen werden: Stream Processing für Pipeline-artige Transformationen, Traditional Processing für komplexe Geschäftslogik mit expliziter Kontrolle.

Die Konzepte von Stream Processing ergänzen die bisherigen Event-Driven Architecture Patterns und bieten eine alternative Sichtweise auf Event-Verarbeitung, die in bestimmten Kontexten sehr wertvoll sein kann.