Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Einführung in Prozessmanager und die nachricht...

Einführung in Prozessmanager und die nachrichtengetriebene Architektur

Avatar for Alexander Langer

Alexander Langer

May 15, 2018

Other Decks in Technology

Transcript

  1. @alxlngr Aggregate • Aggregate schützen Invarianten
 
 An invariant is

    a business rule that must always be consistent. There are different kinds of consistency. One is transactional, which is considered immediate and atomic. There is also eventual consistency. When discussing invariants, we are referring to transactional consistency.
 - Vaughn Vernon, Effective Aggregate Design
  2. @alxlngr Beispiel: Cargo Sh*pping • Invariante: Gesamtsumme ist Summe der

    Positionen
 public class Bestellung { private final int bestellnummer; private BigDecimal gesamtsumme = BigDecimal.ZERO; private List<Position> positionen = new ArrayList<>(); public Bestellung(int bestellnummer) { this.bestellnummer = bestellnummer; } public void NehmePositionAuf(int anzahl, int sku, BigDecimal betrag) { int nummer = this.positionen.size(); Position pos = new Position(nummer, anzahl, sku, betrag); this.positionen.add(pos); this.gesamtsumme = this.gesamtsumme.add(pos.betrag); } // mehr }
  3. @alxlngr Prozesse als Service • Services implementieren Prozesse
 
 When

    a significant process or transformation in the domain is not a natural responsibility of an ENTITY or VALUE OBJECT, add an operation to the model as standalone interface declared as a SERVICE. Define the interface in terms of the language of the model and make sure the operation name is part of the UBIQUITOUS LANGUAGE. Make the SERVICE stateless.
 - Eric Evans, Domain-Driven Design
  4. @alxlngr Bestellabwicklung public class Bestellabwicklung { private IBestellungRepository bestellungRepository; private

    IZahlungRepository zahlungRepository; public Bestellabwicklung(IBestellungRepository bR, IZahlungRepository zR) { this.bestellungRepository = bR; this.zahlungRepository = zR; } public void ErfasseZahlung(int bestellnummer, BigDecimal betrag, LocalDateTime wertstellung) { Bestellung bestellung = bestellungRepository.betellungMitBestellnummer(bestellnummer); Zahlung zahlung = zahlungRepository.zahlungFuerBestellung(bestellnummer); zahlung.eingegangen(betrag, wertstellung); bestellung.bereitZumVersand(); } }
  5. @alxlngr Bestellabwicklung public class Bestellabwicklung { private IBestellungRepository bestellungRepository; private

    IZahlungRepository zahlungRepository; public Bestellabwicklung(IBestellungRepository bR, IZahlungRepository zR) { this.bestellungRepository = bR; this.zahlungRepository = zR; } public void ErfasseZahlung(int bestellnummer, BigDecimal betrag, LocalDateTime wertstellung) { Bestellung bestellung = bestellungRepository.betellungMitBestellnummer(bestellnummer); Zahlung zahlung = zahlungRepository.zahlungFuerBestellung(bestellnummer); zahlung.eingegangen(betrag, wertstellung); bestellung.bereitZumVersand(); } }
  6. @alxlngr Aggregate vs. Prozesse • Atomare Konsistenz (Aggregate)
 
 vs.


    
 eventuelle Konsistenz (Prozesse) • Simulation von atomarer Konsistenz von Prozessen über Datenbank-Transaktionen
  7. @alxlngr Command Handler public class CommandHandler { private IUnitOfWork unitOfWork;

    private IBestellungRepository bR; private IZahlungRepository zR; public CommandHandler(IUnitOfWork unitOfWork, IBestellungRepository bR, IZahlungRepository zR) { this.unitOfWork = unitOfWork; this.bR = bR; this.zR = zR; } public void handle(ErfasseEingegangeneZahlung cmd) { unitOfWork.Begin(); Bestellabwicklung abwicklung = new Bestellabwicklung(bR, zR); abwicklung.zahlungEingegangen(cmd.getBestellnummer(), cmd.getBetrag(), cmd.getWertstellung()); unitOfWork.Commit(); } }
  8. @alxlngr Problem: Infrastruktur • Updates über verschiedene Aggregate
 (hier: Bestellung

    und Zahlung) • Persistenz muss (verteilte) DB-Transaktionen erlauben • Anforderungen an Infrastruktur leaken in Domäne
 (muss implizit modelliert werden, ohne dass in der Domäne eine entsprechende Anforderung existiert)
  9. @alxlngr Verteilte Transaktionen • Prozess umfasst mehrere Systeme • Microservices/SCS

    (mit jeweils eigener DB) • externe Systeme/Legacy Software • 2PC häufig keine Option • 2PC-Coordinator ist SPOF • Performance • bei vielen DBs/externen System nicht möglich • CAP-Theorem: -Availability
  10. @alxlngr 1 Aggregat/Transaktion • Aggregat ist bereits consistency boundary! •

    Aggregate so modellieren, dass pro DB-Transaktion genau ein Aggregat geupdated wird • führt jedoch schnell zu großen
 “Cluster Aggregaten”
 
 
 
 
 Vaughn Vernon: Effective Aggregate
 Design, Part I: Modeling a Single Aggregate
  11. @alxlngr Problem: Nebenläufigkeit • viele User, die parallel an einer

    Sache arbeiten • Optimistisches Locking: häufig Fehler • Pessimistisches Locking: Performance und Skalierbarkeit
 • => Transaktionen (= Aggregate!) kleiner machen
 
 
 

  12. @alxlngr kleine Aggregate • Extrem: für jede Invariante ein Aggregat

    (sinnvoll?) • Informationen müssen ausgetauscht werden • führt in (Geschäfts-)Prozessen, die mehrere Aggregate umfassen, zwangsläufig zu eventual consistency • diese muss überwacht/gesteuert werden
 => Prozessmanager
  13. @alxlngr Problem: Zeit • Bsp.: Anforderung: Gutschrift bei Überweisung soll

    verspätet erfolgen (Liquidität) • Bsp.: Ergebnis/nächster Schritt erst später bekannt
 (z.B. Bestellung - Zahlungseingang - Verpackung - Versand) • Lösung: Zustand des Prozesses speichern
 => Prozesse benötigen eine ID
  14. @alxlngr Prozesspersistenz unitOfWork.Begin(); Bestellabwicklung abwicklung = repository.AbwicklungFuerBestellung(cmd.getBestellnummer()); abwicklung.zahlungEingegangen(betrag, wertstellung); unitOfWork.Commit();

    // später unitOfWork.Begin(); Bestellabwicklung abwicklung = repository.AbwicklungFuerBestellung(cmd.getBestellnummer()); abwicklung.versendeBestellung(versandzeitpunkt); unitOfWork.Commit();
  15. @alxlngr Prozessmanager / Saga • entspricht Geschäftsprozessen • macht eventual

    consistency explizit und koordiniert Aggregate / Systeme • reagiert auf Ereignisse (z.B. Commands, Events, Zeit) • hat Zustand (mind. aktueller Prozessfortschritt)
 => “correlation ID” • Prozessmanager ist selbst ein Aggregat - Invarianten? • kann natürlich auch event sourced sein
  16. @alxlngr Sagas vs. Prozessmanager • Saga nach Garcia-Molina/Salem:
 Ersatz für

    verteilte Transaktionen • Kompensierung • Microservices • mehrere BCs • Prozessmanager: • Aggregate • oft ein BC • Geschäftsprozesse
  17. @alxlngr Kompensierung • Rollback von Transaktion über mehrere Aggregate /

    Microservices hinweg nicht möglich • (nicht-technische) Fehler in der Domäne explizit modellieren • für jeden Fehlerfall eine Aktion: • => Domänenexperten • => Compensating Action • => wenn nicht klar: Benutzer entscheiden lassen
  18. @alxlngr Implementierung public class BestellabwicklungSaga : FluentWorkflowModule<BestellabwicklungSagaState, Guid, IEvent> {

    public BestellabwicklungSaga() { On<BestellungEingegangen>().Return(e => e.BestellungId, (s, e) => new ErstelleRechnung(e.BestellungId, e.Besteller, e.Summe)); On<RechnungErstellt>().Return(e => e.BestellungId, (s, e) => new FordereZahlungAn(e.RechnungId)); // … } }
  19. @alxlngr Beispiele • PM als natürliche Ergänzung zum Event Sourcing

    • Rechnungsnummerierung I + II • Eindeutigkeit von Benutzernamen (I, II, III) • Teams • Leistungserfassung
  20. @alxlngr # Teams/Person • jede Person darf nur in höchstens

    Team sein
 jedes Team darf höchstens 11 Mitglieder enthalten
  21. @alxlngr Überschneidungsfreie Leistungserfassung • Betreuer dürfen Einzel- und Gruppenunterricht geben

    • Betreuer können immer nur eine Einheit gleichzeitig durchführen • Schüler können immer nur an einer Stunde gleichzeitig teilnehmen • jede Stunde muss dokumentiert werden • Dokumentation in der Regel nachträglich (abends, WE)
  22. @alxlngr Beispiel: Leistungsüberschneidung • Betreuer dürfen Einzel- und Gruppenunterricht geben

    • Betreuer können immer nur eine Einheit gleichzeitig durchführen • Schüler können immer nur an einer Stunde gleichzeitig teilnehmen • jede Stunde muss dokumentiert werden
  23. @alxlngr Vorteile • SRP • Testbarkeit • kleine Komponenten lassen

    sich leicht ersetzen • automatisch parallelisierbar und skalierbar • Resilienz gegen Teilausfälle • at-most-once - Timeout und Retry
  24. @alxlngr Nachteile • erfordert Umdenken • Komplexität • simpler Funktionsaufruf

    vs. Message • Unit of Work vs. viele zusätzliche Klassen • hohe Einstiegshürden - komplexe Infrastruktur
  25. @alxlngr Beobachtung • Aggregat reagiert auf eine Nachricht und erzeugt

    als Ergebnis 0..n Nachrichten • Aggregate lassen sich sogar pure implementieren:
 (state, nachricht) -> (state')
 bzw.
 (nachrichten[], nachricht) -> nachrichten'[] • eine DB-Zeile pro DB-Transaktion (State-Persistenz)
 bzw.
 ein Stream pro DB-Transaktion (event sourced) • sonst keine Seiteneffekte • => kein Locking notwendig
 => massiv parallel verarbeitbar
  26. @alxlngr Aktorenmodell • Aktoren kommunizieren über Nachrichten • Jeder Aktor

    hat: • eine Adresse (ID) • Posteingang • Verhalten • Aggregate / Prozessmanager sind natürliche Aktoren
  27. @alxlngr Aktorenmodell / Architektur • Jedes Aggregat / jeder Prozessmanager:

    • empfängt eindeutig adressierte Nachrichten (Aggregat ID) • arbeitet sie der Reihe nach ab (Posteingang) • pro Nachricht eine DB-Transaktion (ggfs. Batching) • Implementierung der Aktoren funktional oder objektorientiert • Nachrichten in Smalltalk näher am Aktorenmodell als an heutigen objektorientierten Sprachen
 
 I invented the term object-oriented, and I can tell you that C++ wasn't what I had in mind.
 - Alan Kay (Smalltalk-Erfinder)
  28. @alxlngr Fazit • Prozessmanager / Sagas erlauben saubere Modellierung von

    Invarianten in Aggregaten (consistency boundaries) • unverzichtbar für langlebige Geschäftsprozesse (mit Zeitelement) • Nachrichtengetriebene Architektur natürliche Wahl, da nah an der Domäne, einfach zu implementieren, wenig Kopplung • ideale Ergänzung zum Event Sourcing und Event Storming (Trigger!) • extrem skalierbar • Aktorenmodell natürliche Erweiterung
  29. @alxlngr Weitere Infos • Chris Richardson: Data Consistency in Microservices

    using Sagas
 https://www.youtube.com/watch?v=7dy5WPSv2DQ • Udi Dahan: If (domain logic) then CQRS, or Saga?
 https://www.youtube.com/watch?v=fWU8ZK0Dmxs