Event-Driven Architecture auf Azure: Wann, warum und wie
Praxisleitfaden für Event-Driven Architecture auf Azure — Event Grid, Service Bus, Event Hubs, CQRS und Saga-Muster erklärt.
Event-Driven Architecture (EDA) ist kein Allheilmittel — doch wenn das Problem passt, ist die Wirkung transformativ. Die Herausforderung für Enterprise-Teams liegt darin zu erkennen, wann EDA die richtige Wahl ist, welche Azure-Dienste für welches Szenario taugen und wie man die Fallstricke vermeidet, die ereignisgesteuerte Systeme in Debugging-Albträume verwandeln.
Dieser Leitfaden ist die verdichtete Fassung unserer Architektur-Workshops, gestützt auf Produktionssysteme, die täglich Millionen von Events verarbeiten.
Wann Event-Driven Architecture Sinn ergibt
EDA bringt Komplexität mit sich. Diese Komplexität ist gerechtfertigt, wenn Sie:
- Zeitliche Entkopplung benötigen: Der Produzent soll nicht auf den Konsumenten warten, und beide können in unterschiedlichen Takten arbeiten.
- Mehrere Konsumenten für dasselbe Ereignis haben: Eine Aktion löst Reaktionen in mehreren Bounded Contexts aus (z. B. eine Bestellung löst Lager, Versand, Benachrichtigungen und Analytics aus).
- Lastspitzen abfangen müssen: Der Traffic ist stossartig und nachgelagerte Systeme können nicht so schnell skalieren wie die vorgelagerten Produzenten.
- Audit-Anforderungen erfüllen müssen: Sie brauchen eine vollständige, unveränderliche Historie von Ereignissen.
Wann EDA die falsche Wahl ist:
- Einfache CRUD-Anwendungen mit einer einzelnen Datenbank
- Szenarien, die synchrone, sofortige Antworten erfordern
- Teams ohne operative Reife für verteiltes Debugging
- Domänen, in denen Eventual Consistency nicht akzeptabel ist
Faustregel: Wenn Ihr System innerhalb desselben HTTP-Requests mit „Ja, das ist erledigt" antworten muss, ist Event-Driven der falsche Standard. Nutzen Sie synchrone Verarbeitung und ziehen Sie Events nur für Seiteneffekte in Betracht.
Den richtigen Azure-Dienst wählen
Azure bietet drei zentrale Messaging-Dienste. Den falschen zu wählen ist ein häufiger und teurer Fehler.
Azure Event Grid
Was es ist: Leichtgewichtiger Event-Routing-Dienst, optimiert für reaktive, ereignisgesteuerte Szenarien.
Einsetzen, wenn:
- Sie auf Azure-Ressourcen-Events reagieren müssen (Blob erstellt, Ressourcengruppe geändert)
- Sie einfaches Pub/Sub mit Filterung nach Eventtyp oder Subject wollen
- Events Benachrichtigungen sind („etwas ist passiert"), keine Commands („tue dies")
- Sie nahezu Echtzeit-Zustellung mit niedriger Latenz brauchen
Einschränkungen: Keine Reihenfolge-Garantie, begrenzte Retry-Fähigkeiten, maximale Event-Grösse von 1 MB. Nicht geeignet für Hochdurchsatz-Streaming.
Azure Service Bus
Was es ist: Enterprise-Message-Broker mit umfassenden Queuing- und Pub/Sub-Fähigkeiten.
Einsetzen, wenn:
- Sie garantierte geordnete Zustellung brauchen (Sessions)
- Sie Exactly-Once-Verarbeitungssemantik benötigen
- Nachrichten Commands sind, die zuverlässig verarbeitet werden müssen
- Sie Dead-Letter-Queues, geplante Zustellung oder Message Deferral brauchen
- Transaktionsunterstützung über mehrere Queues/Topics hinweg erforderlich ist
Dies ist die Standardwahl für die meisten Enterprise-Szenarien. Der Funktionsumfang deckt 80 % der Anwendungsfälle ab.
Azure Event Hubs
Was es ist: Hochdurchsatz-Datenstreaming-Plattform (vergleichbar mit Apache Kafka).
Einsetzen, wenn:
- Sie Telemetrie, Logs oder IoT-Daten in massivem Umfang aufnehmen (Millionen Events pro Sekunde)
- Sie Consumer Groups benötigen, die in eigenem Tempo lesen
- Sie Events ab einem bestimmten Zeitpunkt erneut abspielen wollen
- Event-Reihenfolge innerhalb einer Partition erforderlich ist
Wesentlicher Unterschied: Event Hubs speichert Events für einen konfigurierbaren Zeitraum (bis zu 90 Tage). Konsumenten ziehen Events — der Broker pusht nicht.
Entscheidungsmatrix
| Anforderung | Event Grid | Service Bus | Event Hubs |
|---|---|---|---|
| Pub/Sub-Benachrichtigungen | Optimal | Gut | Überdimensioniert |
| Command-Verarbeitung | Nein | Optimal | Nein |
| Geordnete Zustellung | Nein | Ja (Sessions) | Ja (Partition) |
| Hochdurchsatz-Streaming | Nein | Moderat | Optimal |
| Dead-Letter-Behandlung | Begrenzt | Vollständig | Manuell |
| Event Replay | Nein | Nein | Ja |
CQRS implementieren: Lesen und Schreiben trennen
Command Query Responsibility Segregation (CQRS) passt auf natürliche Weise zu EDA. Die Kernidee: unterschiedliche Modelle für das Lesen und Schreiben von Daten verwenden.
Wann CQRS Mehrwert schafft:
- Lese- und Schreiblasten haben unterschiedliche Skalierungsanforderungen
- Das Lesemodell muss für Query-Performance denormalisiert sein
- Mehrere Bounded Contexts benötigen unterschiedliche Sichten auf dieselben Daten
Praktische Implementierung auf Azure:
- Schreibseite: Commands werden verarbeitet, Domänen-Events an Service Bus publiziert.
- Event-Handler: Abonnieren Events und aktualisieren leseoptimierte Projektionen (z. B. in Azure Cosmos DB oder Azure SQL).
- Leseseite: Queries treffen direkt auf den denormalisierten Read Store — keine Joins, keine komplexen Queries.
Kritische Überlegungen:
- Eventual Consistency ist inhärent. Das Lesemodell wird dem Schreibmodell hinterherhinken. Entwerfen Sie Ihre UI entsprechend (z. B. Weiterleitung auf eine Bestätigungsseite, statt sofort das Lesemodell abzufragen).
- CQRS nicht überall anwenden. Einfache Domänen mit geringer Lese-/Schreib-Asymmetrie gewinnen nur Komplexität.
- Projektions-Rebuilds müssen möglich sein. Events dauerhaft speichern, damit Lesemodelle bei Schemaänderungen von Grund auf neu aufgebaut werden können.
Event Sourcing: Wenn das Event-Log zur Wahrheit wird
Event Sourcing geht weiter als CQRS: Statt den aktuellen Zustand zu speichern, speichern Sie jedes Ereignis, das den Zustand verändert hat.
Überzeugende Anwendungsfälle:
- Finanzsysteme, in denen Nachvollziehbarkeit nicht verhandelbar ist
- Domänen, in denen das Verständnis von „wie sind wir hierhin gekommen" ebenso wichtig ist wie „wo stehen wir"
- Systeme, die den Zustand zu jedem beliebigen Zeitpunkt rekonstruieren müssen
Realitäten der Implementierung:
- Event Store: Azure Cosmos DB mit Change Feed verwenden oder eine dedizierte Event-Store-Bibliothek wie Marten (PostgreSQL).
- Snapshots: Bei Aggregaten mit Tausenden von Events periodisch Snapshots erstellen, um nicht den gesamten Event-Stream abspielen zu müssen.
- Schema-Evolution: Events sind unveränderlich. Wenn sich Ihr Event-Schema ändern muss, nutzen Sie Upcasting (Transformation alter Events in das neue Format zur Lesezeit).
- Speicherkosten: Events akkumulieren. Archivierung einplanen — Events älter als N Monate in Cold Storage verschieben.
Achtung: Event Sourcing ist mächtig, bringt aber erhebliche Komplexität mit sich. Wir empfehlen es nur, wenn der geschäftliche Wert eines lückenlosen Audit Trails die Investition in das Engineering rechtfertigt.
Das Saga-Muster: Verteilte Transaktionen koordinieren
In einer Microservices-Welt können Sie keine Datenbank-Transaktionen über Service-Grenzen hinweg nutzen. Das Saga-Muster koordiniert mehrstufige Geschäftsprozesse über Events.
Choreografie (bevorzugt für einfache Sagas):
Jeder Service lauscht auf Events und publiziert eigene. Kein zentraler Koordinator.
OrderService -> OrderPlaced
InventoryService (lauscht) -> InventoryReserved
PaymentService (lauscht) -> PaymentProcessed
ShippingService (lauscht) -> ShipmentScheduledOrchestrierung (bevorzugt für komplexe Sagas):
Ein zentraler Saga-Orchestrator steuert den Ablauf und die Kompensationslogik.
SagaOrchestrator:
1. ReserveInventory-Command senden -> auf Antwort warten
2. ProcessPayment-Command senden -> auf Antwort warten
3. ScheduleShipment-Command senden -> auf Antwort warten
Bei Fehler in jedem Schritt -> Kompensations-Commands sendenPraxisempfehlungen:
- Choreografie funktioniert bei 3-4 Schritten. Darüber hinaus wird der implizite Ablauf unmöglich nachzuvollziehen.
- Orchestrierung ist besser für komplexe Abläufe mit bedingter Logik, Timeouts und manuellen Eingriffen.
- MassTransit bietet exzellente Saga-State-Machine-Unterstützung für .NET, inklusive Persistenz in Azure SQL oder Cosmos DB.
- Immer kompensierende Aktionen definieren. Wenn die Zahlung fehlschlägt, nachdem das Lager reserviert wurde, muss die Saga die Reservierung freigeben.
Dead-Letter-Behandlung: Das Sicherheitsnetz
Dead-Letter-Queues (DLQ) sind der Ort, an dem Nachrichten landen, wenn sie nicht verarbeitet werden können. Sie zu ignorieren bedeutet, Produktionsfehler zu ignorieren.
Eine robuste Dead-Letter-Strategie:
- DLQ-Tiefe überwachen mit Azure Monitor Alerts. Eine wachsende DLQ ist ein Symptom eines Bugs, kein Feature.
- Eine Dead-Letter-Verarbeitungspipeline bauen: Inspizieren, diagnostizieren, beheben und wiederholen. Nachrichten nicht manuell erneut senden.
- Fehler kategorisieren: Transient (wiederholen), Poison (untersuchen und verwerfen), Schema-Mismatch (Consumer fixen und wiederholen).
- Angemessenen
MaxDeliveryCountsetzen: Zu niedrig und Sie dead-lettern bei transienten Fehlern; zu hoch und Sie verzögern die Erkennung. Unser Standard: 5-10. - Kontext bewahren: Exception, Message Body und Trace ID beim Verschieben in die DLQ protokollieren.
Tooling-Empfehlung: Bauen Sie ein internes „DLQ-Dashboard", das Betriebsteams nutzen können, um Dead-Letter-Nachrichten zu inspizieren, erneut abzuspielen oder zu verwerfen. Das amortisiert sich innerhalb von Wochen.
Architektur-Checkliste
Bevor Sie Event-Driven Architecture auf Azure einführen:
- Klare Event-Produzenten und -Konsumenten identifiziert
- Den korrekten Azure-Messaging-Dienst pro Szenario gewählt
- Event-Schemas mit Versionierungsstrategie definiert
- Kompensationslogik für verteilte Transaktionen entworfen
- Dead-Letter-Monitoring und Replay-Prozeduren etabliert
- Eventual Consistency akzeptiert und die UI entsprechend gestaltet
- Distributed Tracing über alle Event-Flows implementiert
Bei CC Conceptualise entwerfen und implementieren wir Event-Driven Architectures auf Azure, die realer Komplexität standhalten. Wenn Sie EDA für Ihr Unternehmen evaluieren, sprechen Sie uns an.