Table of Contents

Was ist Event Driven Architecture und warum es jetzt wichtig ist

Event Driven Architecture (EDA) ist zu einem Eckpfeiler des modernen Microservices-Designs geworden. Während Unternehmen ihre verteilten Systeme skalieren, führt das traditionelle synchrone Anfrage-Antwort-Modell eine enge Kopplung, kaskadierende Ausfälle und begrenzten Durchsatz ein. EDA löst diese Probleme, indem es die Kommunikation auf asynchrone Ereignisse verlagert - Dienste veröffentlichen Fakten darüber, was passiert ist, und andere Dienste reagieren unabhängig. Dieser Leitfaden behandelt die Kernkonzepte, Muster, Technologien und praktische Schritte, die Sie benötigen, um ereignisgesteuerte Microservices zu erstellen, die skalierbar, belastbar und wartbar sind.

Grundprinzipien der Event Driven Architecture

Asynchrone Kommunikation

Dienste warten nicht auf eine Antwort nach der Veröffentlichung eines Ereignisses. Der Produzent veröffentlicht ein Ereignis bei einem Nachrichtenbroker und setzt seine Arbeit sofort fort. Verbraucher verarbeiten Ereignisse in ihrem eigenen Tempo. Dieses nicht blockierende Verhalten maximiert den Durchsatz und hält die Dienste reaktionsfähig, auch wenn nachgelagerte Komponenten langsam oder nicht verfügbar sind. Es bedeutet auch, dass vorübergehende Ladespitzen durch die Warteschlange des Brokers absorbiert werden, wodurch eine Überflutung der Anfrage verhindert wird.

Lose Kupplung

Produzenten und Konsumenten kennen sich nicht direkt. Ein Produzent veröffentlicht Events zu einem Thema, ohne zu wissen, welche Dienste sie verbrauchen werden. Ein neuer Konsument kann ein bestehendes Eventthema abonnieren, ohne dass es Änderungen beim Produzenten gibt. Diese Entkopplung ermöglicht es Teams, Dienste unabhängig zu entwickeln, einzusetzen und zu skalieren. Es erleichtert auch, alte Dienste zu ersetzen oder auszulagern, ohne das System zu zerstören.

Ereignisunveränderlichkeit

Einmal veröffentlicht, kann ein Ereignis nicht mehr geändert werden. Ereignisse stellen Fakten über vergangene Ereignisse dar – ein registrierter Kunde, eine aufgegebene Bestellung, eine abgeschlossene Zahlung. Unveränderlichkeit bietet einen zuverlässigen Audit-Trail, vereinfacht das Debugging und ermöglicht die Wiederholung von Ereignissen für die Wiederherstellung oder das Testen. Es passt auch natürlich zur Ereignisbeschaffung, wo das Ereignisprotokoll zur maßgeblichen Quelle der Wahrheit wird.

Eventuelle Konsistenz

Eventgesteuerte Systeme handeln mit starker Konsistenz hinsichtlich Verfügbarkeit und Partitionstoleranz. Nach der Veröffentlichung eines Events kommt es zu einer Verzögerung, bevor alle Verbraucher ihren Status aktualisieren. Anwendungen müssen so gestaltet sein, dass sie mit temporären Inkonsistenzen umgehen. Beispielsweise kann eine E-Commerce-Site einige Sekunden nach der Einreichung "Auftrag ausstehend" anzeigen, während Inventar-, Zahlungs- und Versanddienste das Event verarbeiten. Benutzeroberflächen und Geschäftsworkflows sollten so gebaut werden, dass sie dies anmutig handhaben.

Schlüsselkomponenten eines ereignisgesteuerten Systems

Event-Produzenten

Hersteller erkennen bedeutsame Zustandsänderungen und veröffentlichen Ereignisse. Sie sollten sich auf geschäftsrelevante Ereignisse konzentrieren, nicht auf technische Ereignisse auf niedriger Ebene. Anstatt "Datenbankzeile aktualisiert" zu veröffentlichen, veröffentlichen sie "Kundenadresse geändert". Die Hersteller benötigen zuverlässige Zustellmechanismen, einschließlich Wiederholungen und Bestätigungen vom Broker. Sie sollten genügend Kontext in die Ereignisnutzlast einschließen, damit die Verbraucher ohne synchrone Anrufe zum Hersteller handeln können.

Eventverbraucher

Verbraucher müssen idempotent sein: die zweimalige Verarbeitung desselben Ereignisses sollte die gleiche Wirkung haben wie die einmalige Verarbeitung. Dies ist von entscheidender Bedeutung, da die meisten Nachrichtenbroker mindestens einmal Lieferung liefern. Verbraucher sollten auch eine ordnungsgemäße Fehlerbehandlung durchführen, wobei zwischen vorübergehenden Ausfällen (Wiederholung mit Backoff) und dauerhaften Ausfällen (Senden in Warteschlange mit toten Buchstaben) unterschieden wird.

Message Broker / Event Bus

Der Broker sitzt zwischen Produzenten und Verbrauchern und verwaltet das Routing, die Persistenz und die Lieferung von Ereignissen. Er bietet den Publish-Subscribe-Mechanismus, der eine lose Kopplung ermöglicht.

  • Persistenz: Ereignisse überleben den Neustart des Brokers.
  • Garantierte Lieferung: Mindestens einmal oder genau einmal Semantik.
  • Ordering Guarantees: Innerhalb einer Partition oder eines Themas.
  • Skalierbarkeit: Horizontale Partitionierung, um hohen Durchsatz zu bewältigen.
  • Dead-letter-queues: For failed message handling.

Themen und Kanäle

Ereignisse werden in Themen oder Kanäle gegliedert. Ein Thema gruppiert Ereignisse, die mit dem Thema in Zusammenhang stehen, zum Beispiel "order events" oder "payment events". Die Granularität von Themen ist eine Designentscheidung: zu grob und die Verbraucher erhalten viele irrelevante Ereignisse; zu fein und Sie haben eine Explosion von Themen. Ein gängiger Ansatz ist es, Themen in begrenzte Kontexte oder Domänenaggregate zu übertragen.

Wann Sie Event Driven Architecture vs. Request-Response verwenden sollten

EDA ist nicht für jedes Szenario die richtige Wahl, sondern verwenden Sie sie, wenn:

  • Sie benötigen eine unabhängige Skalierung der Dienste.
  • Systemresilienz erfordert, dass ein Serviceausfall nicht kaskadiert.
  • Sie haben mehrere Verbraucher für die gleichen Daten oder Aktionen.
  • Die Reaktion in Echtzeit auf Zustandsänderungen ist kritisch.
  • Sie wollen einen unveränderlichen Audit-Trail aller Geschäftsereignisse.

EDA vermeiden, wenn:

  • Ihr Anwendungsfall erfordert sofortige starke Konsistenz (z. B. Finanzbuchaktualisierungen).
  • Sie haben einen einfachen, linearen Fluss mit wenigen Diensten.
  • Ihrem Team fehlt es an Erfahrung mit asynchronen Systemen und eventueller Konsistenz.
  • Synchrone Antworten mit niedriger Latenz sind für benutzerbezogene Anfragen erforderlich.

Viele Systeme verwenden einen hybriden Ansatz: Synchrone APIs für einfache CRUD-Operationen und ereignisgesteuerte Muster für komplexe Workflows, Integrationen und Echtzeitfunktionen.

Gemeinsame Event Driven Architekturmuster

Meldung von Ereignissen

Das einfachste Muster: ein leichtes Ereignis mit minimalen Daten (oft nur eine ID und ein Ereignistyp) wird veröffentlicht, um Verbraucher zu benachrichtigen. Verbraucher fragen dann den Hersteller nach Details ab. Dies minimiert die Nutzlast des Ereignisses, führt aber eine Kopplung ein, weil Verbraucher wissen müssen, wie sie den Hersteller abfragen müssen. Verwenden Sie, wenn die Ereignisgröße klein sein muss und die Abfragelatenz akzeptabel ist.

Staatliche Übertragung von Ereignissen

Ereignisse tragen alle Daten, die Verbraucher benötigen. Wenn ein Kunde seine Adresse ändert, beinhaltet das Ereignis die vollständige neue Adresse. Dies eliminiert die Notwendigkeit für synchrone Abfragen, reduziert die Kopplung und verbessert die Verbraucherleistung. Der Kompromiss sind größere Ereignisse und potenzielle Datenvervielfältigung über Dienste hinweg. Dies ist das häufigste Muster in modernen ereignisgesteuerten Microservices.

Event Sourcing

Der Zustand des Systems wird aus dem Ereignisprotokoll abgeleitet und nicht direkt gespeichert. Jede Zustandsänderung wird als unveränderliches Ereignis angehängt. Der aktuelle Zustand wird durch Wiedergabe von Ereignissen rekonstruiert (möglicherweise mit Snapshots für die Performance). Die Ereignisbeschaffung bietet perfekte Auditierbarkeit, zeitliche Abfragen und die Möglichkeit, gelesene Modelle neu zu erstellen. Sie erhöht die Komplexität der Schemaentwicklung und erfordert ein sorgfältiges Ereignisdesign. Sie passt auf natürliche Weise zu CQRS.

CQRS (Command Query Responsibility Segregation)

CQRS trennt Schreib- (Befehls-) und Lese- (Abfrage-) Modelle. Befehle generieren Ereignisse, die zur Aktualisierung von Lesemodellen verwendet werden. Dies ermöglicht es Ihnen, jedes Modell unabhängig zu optimieren, beispielsweise mit einem hoch normalisierten Schreibspeicher und einem denormierten Lesespeicher, der für bestimmte Abfragen optimiert ist. CQRS wird oft bei der Ereignisbeschaffung verwendet, kann aber auch unabhängig verwendet werden.

Saga Muster

Sagas koordinieren mehrstufige Transaktionen über Microservices hinweg ohne verteilte Sperren. Jeder Schritt veröffentlicht ein Ereignis, das den nächsten Schritt auslöst. Wenn ein Schritt fehlschlägt, wird der Vorgang kompensiert und frühere Schritte rückgängig gemacht. Es gibt zwei Implementierungsstile:

  • Choreography: Jeder Dienst weiß, welches Ereignis als nächstes nach Abschluss seiner lokalen Transaktion veröffentlicht werden soll.
  • Orchestration: Ein zentraler Koordinator (Saga-Manager) sendet Befehle und hört auf Ereignisse, entscheidet über den nächsten Schritt.

Sagas sind unerlässlich, um die Datenkonsistenz in verteilten, letztlich konsistenten Systemen zu gewährleisten.

Beliebte Technologien für Event Driven Architecture

Apache Kafka

Kafka ist die führende verteilte Streaming-Plattform für hochdurchsatzfähige, fehlertolerante Ereignisverarbeitung. Sie organisiert Ereignisse in Themen, unterstützt Partitionierung für Skalierbarkeit und bietet eine starke Ordnung innerhalb von Partitionen. Kafka behält Ereignisse für einen konfigurierbaren Zeitraum, was sowohl die Echtzeit-Streamverarbeitung als auch die historische Wiederholung ermöglicht. Das Ökosystem umfasst Kafka Streams, Kafka Connect und eine Rich Client Library. Kafka hat eine steile Lernkurve und erfordert erhebliche operative Expertise. Erfahren Sie mehr auf der offiziellen Website.

RabbitMQ

RabbitMQ ist ein ausgereifter, funktionsreicher Nachrichtenbroker, der AMQP und andere Protokolle implementiert. Er unterstützt flexibles Routing durch Austausche und Warteschlangen, Publizieren-Abonnement, Arbeitswarteschlangen und erweiterte Funktionen wie Dead-Buchstaben-Austausch und Prioritätswarteschlangen. RabbitMQ ist einfacher einzurichten und zu bedienen als Kafka, was es zu einer guten Wahl für Teams macht, die neu bei EDA sind, oder für Anwendungsfälle, die keinen extremen Durchsatz oder langfristige Speicherung von Kafka erfordern.

Amazon EventBridge

EventBridge ist ein serverloser Eventbus, der AWS-Dienste, SaaS-Anwendungen und benutzerdefinierte Anwendungen verbindet. Er bietet Schemaregistrierung, Ereignisfilterung, Transformation und native Integration mit Lambda- und Step-Funktionen. EventBridge erfordert kein Infrastrukturmanagement und skaliert automatisch. Er ist ideal für AWS-zentrierte Architekturen, kann jedoch bei sehr hohen Volumina höhere Kosten pro Ereignis haben.

Azure Event Hubs und Service Bus

Azure Event Hubs ist eine Big-Data-Streaming-Plattform für Telemetrie-Einnahme, ähnlich wie Kafka. Azure Service Bus ist ein vollständig verwalteter Enterprise Message Broker für Publish-Abonnement und Warteschlangen mit Funktionen wie Transaktionen, doppelter Erkennung und Dead-lettering. Beide integrieren sich tief in das Azure-Ökosystem.

Google Cloud Pub/Sub

Pub/Sub ist ein vollständig verwalteter, globaler Messaging-Dienst mit mindestens einmaliger Lieferung und automatischer Skalierung. Er unterstützt Push-and-Pull-Lieferung und integriert sich in Google Cloud-Dienste. Er ist eine gute Wahl für GCP-basierte Architekturen.

Design-Events für Ihr System

Granularität des Ereignisses

Ereignisse sollten sinnvolle Geschäftsereignisse auf der richtigen Abstraktionsebene darstellen. Vermeiden Sie technische Ereignisse wie "Datenbankzeile aktualisiert." Stattdessen modellieren Sie Ereignisse um Domänenkonzepte herum: "Kundenregistriert", "Bestellung versendet", "Zahlung fehlgeschlagen." Ereignisse sollten atomar sein - ein Ereignis pro Geschäftstatsache. Wenn Sie mehrere nicht zusammenhängende Änderungen zu einem einzigen Ereignis kombinieren, entsteht eine unerwünschte Kopplung.

Benennungsübereinkommen für Veranstaltungen

Verwende das Vergangenheitsformat, um etwas anzuzeigen, das bereits passiert ist. Fügen Sie den Domänenkontext hinzu, um Mehrdeutigkeiten zu vermeiden: "Billing.InvoiceGenerated" vs. "Shipping.InvoiceGenerated". Konsistenz in der gesamten Organisation macht das System leichter zu verstehen und zu pflegen.

Ereignisschema

Ein Ereignisschema sollte Standardmetadaten enthalten:

  • eventId: Eindeutige Kennung für die Deduplizierung.
  • eventType: Die Art des Ereignisses.
  • timestamp]: Wenn das Ereignis aufgetreten ist.
  • version: Schemaversion.
  • correlationId: Für die Nachverfolgung über Dienste hinweg.

Die Nutzdaten sollten alle Daten enthalten, die Verbraucher benötigen, um das Ereignis ohne zusätzliche Abfragen zu verarbeiten (Ereignis-übertragener Zustandstransfer). Verwenden Sie eine Schemaregistrierung zum Speichern und Erzwingen von Schemas. Wählen Sie ein Serialisierungsformat: JSON ist für den Menschen lesbar, während Avro oder Protobuf eine bessere Leistung und Schemaentwicklung bieten.

Schematische Entwicklung

Ereignisse sind Verträge, und sie werden sich ändern.

  • Fügen Sie Versionsinformationen in jedes Ereignis ein.
  • Rückwärtskompatibilität: Neue Produzenten müssen immer noch mit alten Verbrauchern arbeiten.
  • Verwenden Sie optionale Felder für Additionen; Entfernen oder Umbenennen von Feldern niemals.
  • Verwenden Sie eine Schemaregistrierung, die Kompatibilitätsregeln während der Bereitstellung durchsetzt.
  • Unterstützen Sie mehrere Schemaversionen während der Übergangszeiträume.

Best Practices für die Umsetzung

Idempotenz

Die Verbraucher müssen doppelte Ereignisse sicher behandeln.

  • Speichern Sie verarbeitete Ereignis-IDs und überspringen Sie Duplikate.
  • Verwenden Sie natürliche Idempotenzschlüssel aus der Geschäftsdomäne (z. B. Bestellnummer).
  • Operationen als idempotent zu gestalten (absolute Werte statt Inkrementierung setzen).

Fehlerbehandlung und Retries

Interiente Fehler (Netzwerk-Timeouts, vorübergehende Service-Nichtverfügbarkeit) von permanenten Fehlern (ungültige Daten, Schema-Mismatch) unterscheiden. Exponentielles Backoff mit Jitter für Wiederholungen verwenden. Nach einer maximalen Anzahl von Wiederholungen das Ereignis zur manuellen Inspektion an eine Warteschlange mit toten Buchstaben senden. Warteschlangen mit toten Buchstaben überwachen und Warnmeldungen einrichten.

Bestellung von Veranstaltungen

Globale Bestellungen sind teuer und oft unnötig. Verwenden Sie Partitionsschlüssel (z. B. Customer ID, Order ID), um Ereignisse auf dieselbe Partition zu leiten, um die Ordnung in diesem Kontext sicherzustellen. Erzwingen Sie nur eine strikte Bestellung, wenn die Geschäftslogik davon abhängt, da sie die Skalierbarkeit einschränkt.

Überwachung und Beobachtbarkeit

Schlüsselmetriken verfolgen: Ereignisveröffentlichungsrate, Verbraucherverzögerung, Verarbeitungszeit, Fehlerrate, Warteschlangentiefe mit toten Buchstaben. Verwendet verteilte Tracing mit Korrelations-IDs, um Ereignisse dienstübergreifend zu verfolgen. Richten Sie Warnmeldungen auf Anomalien wie einen plötzlichen Rückgang des Ereignisvolumens oder eine zunehmende Verzögerung der Verbraucher ein. Erstellen Sie Dashboards, die eine Echtzeit-Ansicht des Zustands des Ereignisflusses bieten.

Sicherheit

Ereignisse können sensible Daten enthalten. Authentifizierung und Autorisierung für die Veröffentlichung und das Abonnement implementieren. Ereignisse im Transit (TLS) und im Ruhezustand verschlüsseln. Netzwerksegmentierung verwenden, um den Broker zu isolieren. Zugriff auf Ereignisströme prüfen und Datenaufbewahrungsrichtlinien gemäß Compliance-Anforderungen implementieren. Sensible Felder innerhalb von Ereignisnutzlasten verschlüsseln.

Gemeinsame Herausforderungen und Lösungen

Debugging verteilter Flüsse

Ohne einen einzelnen Call-Stack ist das Tracing von Ereignisflüssen schwierig. Verwenden von Korrelations-IDs in allen Ereignissen und Protokollen. Implementieren Sie verteilte Tracing-Tools wie Jaeger oder Zipkin. Führen Sie ein durchsuchbares Ereignisprotokoll für die Rekonstruktion historischer Sequenzen. Erstellen Sie Ereigniswiedergabefunktionen, um Probleme in Testumgebungen zu reproduzieren.

Event Storms

Ein Ereignissturm tritt auf, wenn Ereignisse kaskadierende Ereignisse auslösen, die möglicherweise unendliche Schleifen erzeugen oder das System überwältigen.

  • Design von Events, die vollständig genug sind, damit die Verbraucher nicht mehr Events veröffentlichen müssen, um Daten zu sammeln.
  • Festlegung der maximalen Wiederholungsgrenzwerte.
  • Leistungsschalter zu implementieren.
  • Überwachung des Ereignisvolumens und Alarmierung auf ungewöhnliche Muster.

Testen von asynchronen Systemen

Das Testen von ereignisgesteuerten Systemen erfordert unterschiedliche Ansätze:

  • Unit-Tests: Verspotten Sie den Broker, überprüfen Sie, ob Dienste Ereignisse korrekt veröffentlichen / konsumieren.
  • Integrationstests: Testcontainer (z.B. Testcontainer für Kafka oder RabbitMQ) verwenden, um den tatsächlichen Ereignisfluss zu überprüfen.
  • Vertragstests: Sicherstellen, dass sich Hersteller und Verbraucher auf Schemata einigen.
  • Chaos Engineering: Testen Sie die Widerstandsfähigkeit durch Simulation von Brokerausfällen, Netzwerkpartitionen und Verbraucherausfällen.

Erste Schritte mit Event Driven Architecture

1. Identifizieren Sie Ihre Veranstaltungen

Führen Sie Workshops für Veranstaltungen durch, in denen Experten Experten auftreten. Identifizieren Sie Ereignisse, die bedeutende Geschäftsereignisse darstellen. Beginnen Sie mit einer kleinen, gut definierten Untermenge, z. B. "OrderPlaced" und "PaymentReceived". Dokumentieren Sie jedes Ereignis: Zweck, Nutzlast, Produzent und Verbraucher.

2. Wählen Sie Ihren Broker

Für Teams, die neu bei EDA sind, sollten Sie einen Managed Service wie Amazon EventBridge oder Google Cloud Pub/Sub in Betracht ziehen, um den Betriebsaufwand zu reduzieren. Wenn Sie einen hohen Durchsatz und eine Wiederholung von Ereignissen benötigen, wählen Sie Kafka trotz seiner Komplexität. Für einfachere Anwendungsfälle ist RabbitMQ ein solider Ausgangspunkt. Berücksichtigen Sie die vorhandene Expertise und Infrastruktur Ihres Teams.

3. Schemata für Planungsereignisse

Standard-Metadatenfelder erstellen, Nutzlasten mithilfe von ereignisübertragenen Zustandsübertragungen entwerfen, ein Serialisierungsformat auswählen (JSON für Einfachheit, Avro/Protobuf für Produktion), wenn möglich eine Schema-Registrierung einrichten, Namenskonventionen und Evolutionsrichtlinien festlegen.

4. Durchführung und Prüfung

Beginnen Sie mit einem einzigen Hersteller und einem oder zwei Verbrauchern. Implementieren Sie Idempotenz, Fehlerbehandlung und Überwachung vom ersten Tag an. Verwenden Sie die Clientbibliotheken des Brokers. Schreiben Sie Integrationstests mit Testcontainern. Richten Sie Dashboards für Verbraucherverzögerungen und Fehlerraten ein.

5. Iteration und Dokument

Erweitern Sie Anwendungsfälle schrittweise. Sammeln Sie Feedback aus Entwicklung und Betrieb. Führen Sie einen Veranstaltungskatalog mit Schemata und Verbraucherinformationen. Dokumentieren Sie architektonische Entscheidungen. Unterweisen Sie Ihr Team in asynchronen Mustern und eventueller Konsistenz.

Real-World Use Cases

E-Commerce-Auftragsbearbeitung

Wenn ein Kunde eine Bestellung aufgibt, löst das "OrderPlaced"-Ereignis mehrere unabhängige Dienste aus: Bestandsreservierung, Zahlungsabwicklung, Versandplanung und Benachrichtigung. Wenn die Zahlung fehlschlägt, gibt ein Ausgleichsereignis das Inventar frei. Jeder Dienst skaliert unabhängig auf der Grundlage seiner eigenen Last. Das Ereignisprotokoll bietet eine vollständige Bestellhistorie für Kundensupport und -analysen.

Echtzeit-Analyse und Betrugserkennung

Klicks von Benutzern, Seitenaufrufe und Transaktionsereignisse werden an Analysedienste gestreamt. Die Stream-Verarbeitung berechnet Echtzeit-Metriken - Conversion-Raten, Sitzungszahlen, Anomalien. Betrugserkennungsdienste verwenden dieselben Ereignisse, um verdächtige Muster sofort zu markieren, anstatt auf Batch-Berichte zu warten.

IoT Sensordatenaufnahme

Millionen von IoT-Geräten veröffentlichen Telemetrieereignisse (Temperatur, Feuchtigkeit, Ort) an einen Nachrichtenbroker. Mehrere Verbraucher übernehmen verschiedene Aufgaben: Datenspeicherung (Zeitreihendatenbank), Anomalieerkennung (Alarmierung), Dashboard-Updates und Schlussfolgerungen für das maschinelle Lernen. Die Partitionierung des Brokers ermöglicht einen massiven Durchsatz, und die Verbraucher können horizontal skaliert werden, um mit dem Datenvolumen Schritt zu halten.

Schlussfolgerung

Event Driven Architecture ist ein leistungsfähiges Paradigma für den Aufbau moderner Microservices, die skalierbar, belastbar und wartbar sind. Durch die Einbeziehung asynchroner Kommunikation, loser Kopplung und Ereignisunveränderlichkeit können Sie die Fallstricke synchron verteilter Systeme vermeiden. Der Schlüssel ist, klein anzufangen, die richtige Technologie basierend auf Ihren Anforderungen auszuwählen und von Anfang an in Idempotenz, Überwachung und Schemamanagement zu investieren. Verwenden Sie die hier beschriebenen Muster und Praktiken, um ereignisgesteuerte Systeme zu entwerfen, die mit Ihrem Unternehmen wachsen können. Weitere Anleitungen zu Microservices-Mustern finden Sie unter Microservices.io und erkunden Sie die CloudEvents-Spezifikation für interoperable Ereignisformate.