CQRS + Event Sourcing: (è corretto che) I comandi sono generalmente comunicati point-to-point, mentre gli eventi di dominio sono comunicati tramite pub / sub?

9

In pratica sto cercando di riprendere il concetto di CQRS e concetti correlati.

Sebbene CQRS non includa necessariamente Messaging ed Event Sourcing sembra essere una buona combinazione (come si può vedere con molti esempi / post di blog che combinano questi concetti)

Dato un caso d'uso per una modifica di stato per qualcosa (ad esempio per aggiornare una domanda su SO), considereresti corretto il seguente flusso (come nella migliore pratica)?

Il sistema emette un UpdateQuestionCommand aggregato che può essere separato in un paio di comandi più piccoli: UpdateQuestion che è mirato alla Domanda Aggregate Root e UpdateUserAction (per contare i punti, ecc.) mirati alla radice di aggregazione utente. Questi vengono inviati in modo asincrono utilizzando la messaggistica point-to-point.

Le radici aggregate fanno le loro cose e se tutto va bene gli eventi fuoco QuestionUpdated e UserActionUpdated rispettivamente, che contengono lo stato che è esternalizzato ad un Event Store .. per essere persistito yadayada, solo per essere completo, non proprio il punto qui.

Questi eventi sono anche messi su un pub / sottocoda per la trasmissione. Qualsiasi sottoscrittore (tra cui probabilmente uno o più proiettori che creano le viste di lettura) è libero di iscriversi a questi eventi.

La domanda generale: è davvero la migliore pratica, che i comandi siano comunicati da punto a punto (cioè: il ricevitore è noto) mentre gli eventi vengono trasmessi (I.e: il / i destinatario / i sono sconosciuti)?

Supponendo quanto sopra, quale sarebbe il vantaggio / svantaggio di consentire ai comandi di essere trasmessi attraverso pub / sub invece di point-to-point?

Ad esempio: Durante la trasmissione di comandi durante l'utilizzo di Saga potrebbe essere un problema, dal momento che il ruolo di mediazione che una Saga deve svolgere in caso di fallimento di una delle radici aggregate è ostacolato, perché la saga non sa a quali radici aggregate partecipare per cominciare.

D'altra parte, vedo i vantaggi (flessibilità) quando i comandi di trasmissione sarebbero consentiti.

    
posta Geert-Jan 20.07.2012 - 02:00
fonte

2 risposte

15

Disclaimler: sto solo muovendo i miei primi passi nel mondo CQRS, ma posso offrire la mia attuale comprensione della questione e vedremo se altri confermeranno. Tutto quello che scrivo qui sotto ha un tema "come la vedo io" e non è autorevole.

Il caso dell'80%

Per rispondere alla tua domanda, i comandi sono davvero un affare da punto a punto. Quando un comando entra in un controller (webapp MVC), quel controller chiede a un dispatcher di comandi di trovare uno e solo un gestore di comandi appropriato, e delega il lavoro a quel gestore.

Perché non pubblicare?

È una questione di responsabilità . Se qualcosa invia un comando, implica l'aspettativa che verrà soddisfatta. Se semplicemente pubblichi e speri che qualcosa da qualche parte lo raccolga e agisca su di esso, non c'è una garanzia che questo sia il caso. Per estrapolazione, non sai nemmeno se più gestori non decidono di agire su un comando, con la conseguenza che la stessa modifica verrà applicata più di una volta.

Gli eventi, d'altra parte, sono di natura informativa ed è ragionevole aspettarsi che zero, due o più componenti siano interessati a un particolare evento. Non ci interessa davvero la portata della modifica richiesta.

Esempio

Questo potrebbe essere paragonato alla vita reale. Se hai tre bambini, entra in una stanza e urla semplicemente "Pulisci il bagno", non hai la garanzia che qualcuno lo farà, e se ne andrà se non sarà fatto due volte (se hai figli obbedienti è così ;-) Dovresti fare meglio se si assegna un bambino specifico per fare ciò che si vuole fare.

Quando quel bambino finisce il suo lavoro, tuttavia, è conveniente se grida "il bagno è stato pulito", così che tutti quelli che vogliono lavarsi i denti sanno che ora possono farlo.

    
risposta data 27.07.2012 - 09:40
fonte
0

Sono d'accordo sul fatto che un sistema di avvio generalmente non si aspetterebbe mai che un comando venga eseguito da più sistemi di destinazione:

  • I comandi di solito non sono mai "invia e prega" - il sistema di avvio di un comando generalmente richiede un feedback asincrono come lo stato e il risultato del comando (es. eventi di stato come acknowledgement e riuscito completion o failure può essere pubblicato dal sistema mirato per informare il sistema di avvio).
  • Se sono coinvolti più sistemi di destinazione, il sistema iniziante riceverebbe più (eventualmente contraddittori) risultati per il comando (ad esempio, l'obiettivo 1 è riuscito, ma il bersaglio 2 non è riuscito). Ciò richiederebbe una maggiore complessità nel determinare lo stato attuale del comando originale (ad esempio, la transazione di comando può essere considerata valida solo se tutti i bersagli sono riusciti? Il comando deve essere ripristinato o compensato in obiettivi di successo se uno dei bersagli fallisce? eccetera.). Ciò introdurrebbe un accoppiamento e una complessità indesiderati tra i sistemi di avvio e di destinazione.

C'è comunque ancora merito di essere in grado di sottoscrivere utenti aggiuntivi (non transazionali, e solitamente piuttosto "promiscui") che "origliano" sui comandi emessi tra i sistemi

  • Finalità di controllo
  • Strumentazione e metriche operative (ad esempio carico, analisi aziendale, ecc.)
  • Elaborazione di eventi complessi o elaborazione di eventi Stream 'intercettazioni' - questi sistemi possono rilevare errori o irregolarità nei comandi (ad es. frequenza di comandi o correlazione tra diverse combinazioni di comandi ed eventi) e possono attivare avvisi o azioni correttive ( spesso sotto forma di ulteriori, diversi tipi di comandi).
risposta data 01.11.2017 - 07:33
fonte

Leggi altre domande sui tag