Softwarearchitektur verstehen und entscheiden

Aaron KreisÜber mich
Konsistenz und Transaktionen

Choreography

Beteiligte reagieren selbstständig auf Ereignisse

Die Idee und ihr Nutzen

Meldet ein Kunde einer Versicherung einen Schaden, müssen danach mehrere Programme tätig werden: Eines prüft, ob der Vertrag den Schaden abdeckt, eines teilt den Fall einer Sachbearbeiterin zu, und eines schickt dem Kunden eine Bestätigung. Dabei gibt es kein zentrales Programm, das diesen Programmen der Reihe nach sagt, was sie tun sollen. Stattdessen meldet jedes Programm über eine Nachrichtenplattform, was es erledigt hat, und die anderen Programme reagieren selbstständig auf diese Nachrichten. Ein neues Programm, das zum Beispiel die gemeldeten Schäden zählt, liest diese Nachrichten einfach mit, und die vorhandenen Programme bleiben unverändert. Diese Art der Zusammenarbeit heißt Choreography, auf Deutsch Choreografie.

Bausteine: Nachrichtenplattform: stellt jedes Ereignis allen angemeldeten Diensten zu; Meldedienst: meldet „Schaden gemeldet“; Deckungsdienst: prüft den Vertrag, meldet das Ergebnis; Zuweisungsdienst: teilt den Fall zu; Benachrichtigungsdienst: schreibt dem Kunden. Verbindungen: Meldedienst → Nachrichtenplattform; Nachrichtenplattform → Deckungsdienst; Deckungsdienst → Nachrichtenplattform; Nachrichtenplattform → Zuweisungsdienst; Nachrichtenplattform → Benachrichtigungsdienst. Kein Programm steuert die anderen; jedes Programm reagiert selbstständig auf die Ereignisse, für die es sich angemeldet hat.

Wie funktioniert es?

Ein Kunde meldet über das Portal der Versicherung einen Wasserschaden. Der Meldedienst, das Programm für eingehende Schadenmeldungen, nimmt die Meldung als Schaden 4711 an und veröffentlicht dazu das Ereignis „Schaden 4711 gemeldet“. Ein Ereignis ist eine Nachricht, die beschreibt, dass etwas geschehen ist. Das Ereignis geht an die Nachrichtenplattform, ein Programm, das Nachrichten entgegennimmt und an alle Dienste zustellt, die sich für diese Art von Nachricht angemeldet haben. Wer das Ereignis empfängt, legt der Meldedienst nicht fest. Der Deckungsdienst hat sich für Ereignisse der Art „Schaden gemeldet“ angemeldet. Die Nachrichtenplattform stellt ihm das Ereignis zu, und der Deckungsdienst prüft, ob der Vertrag des Kunden den Schaden abdeckt. Der Deckungsdienst veröffentlicht sein Ergebnis wieder als Ereignis „Deckung für 4711 bestätigt“. Für dieses Ereignis haben sich zwei Dienste angemeldet, der Zuweisungsdienst und der Benachrichtigungsdienst. Der Zuweisungsdienst teilt den Fall der Sachbearbeiterin Frau Berg zu. Unabhängig davon schickt der Benachrichtigungsdienst dem Kunden eine E-Mail, dass sein Schaden gedeckt ist und bearbeitet wird. Keiner der beiden wartet auf den anderen. Ein Jahr später möchte das Controlling täglich die Zahl neuer Schäden sehen. Das Statistikteam baut dafür einen Statistikdienst, der sich für „Schaden gemeldet“ anmeldet und die Ereignisse zählt.

Die Dienste sind eigenständige Programme, die über das Netz zusammenarbeiten. Verschiedene Teams entwickeln und betreiben sie, und jedes Team ändert seinen Dienst in seinem eigenen Rhythmus. Jeder Dienst meldet sich für die Ereignisarten an, die ihn betreffen, erledigt bei einem passenden Ereignis seinen eigenen Schritt und veröffentlicht sein Ergebnis wieder als Ereignis. Den Aufbau eines Ereignisses legt der Dienst fest, der es veröffentlicht; die Empfänger lesen es nur. Kein Dienst ruft einen anderen direkt auf. Der Meldedienst enthält zum Beispiel keinen Verweis auf den Deckungsdienst. Die Nachrichtenplattform stellt Ereignisse nur zu und trifft keine fachlichen Entscheidungen. Fachlich hängen die Schritte trotzdem voneinander ab: Der Fall wird erst zugewiesen, wenn die Deckung bestätigt ist. Diese Reihenfolge entsteht allein daraus, welcher Dienst auf welches Ereignis reagiert.

Meldedienst und Deckungsdienst bleiben für den Statistikdienst unverändert, weil der Statistikdienst nur mitliest, also Ereignisse empfängt, ohne dass ein anderer Dienst auf sein Ergebnis wartet. Soll dagegen eine neue Betrugsprüfung entscheiden, ob Frau Berg den Fall überhaupt bekommt, genügt Mitlesen nicht. Die beteiligten Teams müssen dann festlegen, ob der Zuweisungsdienst künftig auf ein Ereignis der Betrugsprüfung wartet. Entscheiden sie sich dafür, muss auch der Zuweisungsdienst geändert werden. Ein Vorgang endet, wenn ein vorher festgelegtes Abschlussereignis eintritt oder ein Dienst ein Fehlerereignis meldet. Dass ein Vorgang zu Ende läuft, garantiert die Choreografie nicht. Fällt etwa der Deckungsdienst aus, kommt „Deckung für 4711 bestätigt“ nie an, und der Vorgang steht still, ohne dass ein Dienst einen Fehler meldet. Weil kein Programm den Ablauf überwacht, fällt das nicht von selbst auf. Die beteiligten Teams legen deshalb Fristen fest, und eine Fristüberwachung prüft, ob jeder Vorgang innerhalb seiner Frist seinen Abschluss erreicht. Die Fristüberwachung erkennt zum Beispiel, dass Schaden 4711 nach einer Stunde noch keiner Sachbearbeiterin zugewiesen ist. Gewöhnlich ist ein gemeldeter Schaden nach wenigen Minuten zugewiesen, eine Stunde ohne Zuweisung deutet deshalb auf eine Störung hin.

Choreografie: Dienste reagieren auf Schaden 4711

Beteiligte: Kunde: meldet einen Wasserschaden; Meldedienst: nimmt Meldungen an; Nachrichtenplattform: stellt Ereignisse an alle angemeldeten Dienste zu; Deckungsdienst: prüft den Vertrag; Zuweisungsdienst: teilt den Fall Frau Berg zu; Benachrichtigungsdienst: schreibt dem Kunden; Statistikdienst: kommt ein Jahr später dazu, zählt Schäden. Ablauf: 1. Der Kunde meldet über das Portal einen Wasserschaden. 2. Der Meldedienst nimmt die Meldung als Schaden 4711 an und veröffentlicht auf der Nachrichtenplattform das Ereignis „Schaden 4711 gemeldet“. Wer das Ereignis empfängt, legt der Meldedienst nicht fest. 3. Der Deckungsdienst hat sich für „Schaden gemeldet“ angemeldet, erhält das Ereignis von der Nachrichtenplattform und prüft den Vertrag. 4. Der Deckungsdienst veröffentlicht sein Ergebnis wieder als Ereignis „Deckung für 4711 bestätigt“. 5. Der Zuweisungsdienst erhält „Deckung für 4711 bestätigt“ und teilt den Fall der Sachbearbeiterin Frau Berg zu. 6. Unabhängig vom Zuweisungsdienst schickt der Benachrichtigungsdienst dem Kunden eine E-Mail. Benachrichtigungsdienst und Zuweisungsdienst warten nicht aufeinander. 7. Ein Jahr später meldet sich der neue Statistikdienst für „Schaden gemeldet“ an und zählt neue Schäden. Meldedienst und Deckungsdienst bleiben unverändert.

Wann ist es sinnvoll und wann nicht?

Choreografie lohnt sich

  • Dienste verschiedener Teams arbeiten zusammen und sollen unabhängig voneinander erweitert werden. Mit einem zentralen Steuerprogramm, das die Dienste nacheinander aufruft, müsste dieses Steuerprogramm alle Beteiligten kennen. Für jeden neuen Dienst müsste das Team des Steuerprogramms das Steuerprogramm ändern. Das gälte auch für den Statistikdienst, mit dem dieses Team fachlich nichts zu tun hat. Jede Erweiterung hinge dann von diesem einen Team ab.
  • Der Ablauf hat wenige Schritte, und jeder Dienst reagiert auf ein Ereignis mit einem einzigen Schritt. Beim Wasserschaden sind es drei Schritte, nämlich Deckung prüfen, Fall zuweisen und Kunden benachrichtigen. Die Übersicht, welcher Dienst auf welches Ereignis reagiert, hat dann nur wenige Zeilen. Ein zentrales Steuerprogramm wäre für diese drei Schritte ein zusätzliches Programm, das ein Team entwickeln und betreiben müsste.
  • Neue Empfänger kommen voraussichtlich hinzu und sollen nur mitlesen. Der Statistikdienst ist ein solcher Empfänger. Ohne Choreografie müsste der Meldedienst oder ein zentrales Steuerprogramm den Statistikdienst aufrufen und dafür geändert werden.
  • Schritte, die nicht voneinander abhängen, sollen gleichzeitig laufen. Zuweisungsdienst und Benachrichtigungsdienst arbeiten gleichzeitig. Der Kunde erhält seine E-Mail deshalb nicht erst nach der Zuweisung an Frau Berg.
  • Der Ausfall eines Dienstes soll die übrigen Schritte nicht aufhalten. Fällt der Benachrichtigungsdienst aus, kann der Zuweisungsdienst den Fall trotzdem Frau Berg zuteilen, weil beide Dienste unabhängig voneinander auf das Ereignis reagieren.

Choreografie ist nicht das Richtige

  • Der Ablauf ist lang und verzweigt sich oft. Schritte haben Fristen oder müssen im Fehlerfall rückgängig gemacht werden. Mit Choreografie stünde jede Verzweigung im Code des Dienstes, der auf das jeweilige Ereignis reagiert, Scheitert zum Beispiel die Zuweisung, müsste der Benachrichtigungsdienst auf das Fehlerereignis des Zuweisungsdienstes reagieren und dem Kunden eine Korrektur schicken. Stattdessen steuern die beteiligten Teams den Ablauf mit einer Orchestration: Ein zentrales Steuerprogramm ruft Deckungsdienst, Zuweisungsdienst und Benachrichtigungsdienst der Reihe nach auf. Der ganze Ablauf mit Verzweigungen, Fristen und dem Rückgängigmachen im Fehlerfall steht dann im Code des Steuerprogramms. Niemand muss den Ablauf aus dem Code aller Dienste zusammensuchen.
  • Die Fachabteilung will jederzeit abfragen, in welchem Schritt sich ein bestimmter Schaden wie 4711 gerade befindet. Mit Choreografie kennt kein Programm diesen Stand, und ein zusätzliches Programm müsste ihn aus den Ereignissen aller Dienste zusammensetzen. Stattdessen steuern die beteiligten Teams den Ablauf ebenfalls mit einer Orchestration. Das zentrale Steuerprogramm hält den Stand jedes Schadens fest, und die Fachabteilung fragt ihn dort ab. Das zusätzliche Programm entfällt.
  • Ein Schritt darf erst beginnen, wenn mehrere andere Schritte erfolgreich abgeschlossen sind. Der Zuweisungsdienst darf Schaden 4711 zum Beispiel erst Frau Berg zuteilen, wenn die Deckung bestätigt und die neue Betrugsprüfung abgeschlossen ist. Mit Choreografie müsste der Zuweisungsdienst selbst mitzählen, welche der beiden Ereignisse für Schaden 4711 schon eingetroffen sind. Stattdessen steuern die beteiligten Teams auch diesen Ablauf mit einer Orchestration. Das zentrale Steuerprogramm ruft den Zuweisungsdienst erst auf, wenn beide Prüfungen abgeschlossen sind.

Nachteile und typische Fehler

Der Gesamtablauf ist in keinem einzelnen Dienst festgehalten. Die beteiligten Teams müssen deshalb eine Übersicht pflegen, welcher Dienst auf welches Ereignis reagiert und welches Ereignis er danach meldet. Ohne diese Übersicht lässt sich der Gesamtablauf nur rekonstruieren, indem man den Code aller Dienste liest. Zusätzlich zur Nachrichtenplattform braucht es die Fristüberwachung und eine Ablaufverfolgung, die aufzeichnet, welche Dienste jeder Vorgang durchlaufen hat. Beide müssen betrieben werden. Kein Dienst ruft einen anderen auf, und trotzdem hängt zum Beispiel der Statistikdienst vom Aufbau des Ereignisses „Schaden gemeldet“ ab, den der Meldedienst festlegt. Änderungen am Aufbau der Ereignisse müssen deshalb abwärtsverträglich sein, sodass ältere Empfänger neue Ereignisse weiter lesen können. Der Meldedienst darf zum Beispiel dem Ereignis „Schaden gemeldet“ ein neues Feld hinzufügen, aber kein vorhandenes Feld umbenennen.

Typische Fehler und woran man sie erkennt:

  • Ausbleibendes Ereignis: Ein Dienst stürzt ab, bevor er sein Ereignis veröffentlicht, und der Vorgang läuft nicht weiter. Ohne Fristüberwachung bemerkt das niemand, bis sich der Kunde beschwert. Erkennbar ist das an Schäden, die seit Stunden gemeldet, aber keiner Sachbearbeiterin zugewiesen sind.
  • Endlose Kreisläufe: Der Meldedienst soll einen Schaden nach der Deckungsprüfung als geprüft kennzeichnen und meldet sich dafür für „Deckung bestätigt“ an. Nach jeder Änderung an einem Schaden veröffentlicht der Meldedienst aber „Schaden gemeldet“, auch nach diesem Kennzeichnen. Der Deckungsdienst prüft den Vertrag zu Schaden 4711 deshalb erneut und veröffentlicht wieder „Deckung für 4711 bestätigt“. Darauf kennzeichnet der Meldedienst Schaden 4711 erneut, und der Kreislauf beginnt von vorn. Erkennbar ist das an rasch steigenden Ereigniszahlen auf der Nachrichtenplattform ohne neue Schadenmeldungen.
  • Geänderter Ereignisaufbau: Das Team des Meldedienstes ändert den Aufbau des Ereignisses „Schaden gemeldet“. Vom Statistikdienst weiß das Team des Meldedienstes nichts, weil der Statistikdienst nur mitliest. Der Statistikdienst kann die Ereignisse danach nicht mehr lesen. Erkennbar ist das an Lesefehlern im Statistikdienst unmittelbar nach einer neuen Version des Meldedienstes.
  • Doppelt zugestellte Ereignisse: Die Nachrichtenplattform stellt „Deckung für 4711 bestätigt“ nach einer Störung zweimal zu. Der Benachrichtigungsdienst schickt dem Kunden daraufhin zwei E-Mails. Erkennbar ist das an Kunden, die dieselbe E-Mail doppelt erhalten.
  • Gespeichert, aber nicht gemeldet: Der Deckungsdienst speichert die bestätigte Deckung, fällt aber vor dem Veröffentlichen des Ereignisses aus. Der Schritt ist also erledigt, obwohl das Ereignis nie ankommt. Erkennbar ist das an Schäden mit bestätigter Deckung im Deckungsdienst, die im Zuweisungsdienst nie auftauchen.

Weiterführend

Verwandte Ansätze

  • Event Driven Architecture: die Bauweise, in der Programme über Ereignisse zusammenarbeiten. Choreografie baut darauf auf.
  • Publish Subscribe: beschreibt, wie eine Nachrichtenplattform ein Ereignis an alle angemeldeten Empfänger verteilt.
  • Saga: lange Abläufe über mehrere Dienste, bei denen erledigte Schritte im Fehlerfall durch Gegenschritte rückgängig gemacht werden. Eine Saga lässt sich per Choreografie oder per Orchestration steuern.
  • Distributed Tracing: zeichnet auf, welche Dienste ein Vorgang nacheinander durchläuft, und macht den Ablauf so sichtbar.

Werkzeuge und Umsetzungen

Choreografie braucht vor allem eine Nachrichtenplattform, die Ereignisse verteilt, und eine gemeinsame Beschreibung der Ereignisse:

  • Apache Kafka: Plattform, die Ereignisse dauerhaft speichert und an beliebig viele Empfänger verteilt. Ein neuer Empfänger wie der Statistikdienst kann auch ältere Ereignisse nachlesen, solange Kafka sie aufbewahrt.
  • NATS: Nachrichtenplattform, die Nachrichten in der Grundform nur zustellt, ohne sie zu speichern. Mit der Erweiterung JetStream kann NATS Ereignisse auch dauerhaft speichern.

Quellen