Ich versuche im Grunde, mich mit dem Konzept von CQRS und verwandten Konzepten zu beschäftigen.
Obwohl CQRS Messaging und Event Sourcing nicht unbedingt beinhaltet, scheint es eine gute Kombination zu sein (wie aus vielen Beispielen / Blogposts hervorgeht, die diese Konzepte kombinieren).
Würden Sie angesichts eines Anwendungsfalls für eine Statusänderung für etwas (z. B. um eine Frage zu SO zu aktualisieren) den folgenden Ablauf als korrekt betrachten (wie in der Best Practice)?
Das System gibt einen aggregierten UpdateQuestionCommand aus, der möglicherweise in einige kleinere Befehle unterteilt ist: UpdateQuestion, das auf den Fragenaggregatstamm abzielt, und UpdateUserAction (zum Zählen von Punkten usw.), die auf den Benutzeraggregatstamm abzielen. Diese werden asynchron über Punkt-zu-Punkt-Nachrichten gesendet.
Die aggregierten Wurzeln machen ihr Ding und wenn alles gut geht, feuern sie die Ereignisse QuestionUpdated und UserActionUpdated ab, die einen Status enthalten, der an einen Event Store ausgelagert ist. Yadayada wird beibehalten, nur um vollständig zu sein, hier geht es nicht wirklich darum.
Diese Ereignisse werden auch zur Übertragung in eine Pub / Sub-Warteschlange gestellt. Jeder Abonnent (darunter wahrscheinlich ein oder mehrere Projektoren, die die Leseansichten erstellen) kann diese Ereignisse abonnieren.
Die allgemeine Frage: Ist es in der Tat eine bewährte Methode, dass Befehle Punkt zu Punkt übertragen werden (dh der Empfänger ist bekannt), während Ereignisse gesendet werden (dh die Empfänger sind unbekannt)?
Unter den oben genannten Umständen, was wäre der Vor- / Nachteil, wenn Befehle anstelle von Punkt zu Punkt über Pub / Sub gesendet werden könnten?
Beispiel: Beim Senden von Befehlen während der Verwendung von Saga kann dies ein Problem sein, da die Vermittlungsrolle, die eine Saga bei einem Ausfall einer der aggregierten Wurzeln spielen muss, behindert wird, da die Saga zunächst nicht weiß, an welchen aggregierten Wurzeln sie beteiligt ist .
Andererseits sehe ich Vorteile (Flexibilität), wenn Sendebefehle erlaubt wären.
quelle
Antworten:
Haftungsausschluss: Ich mache nur meine ersten Schritte in der CQRS-Welt, aber ich kann mein aktuelles Verständnis der Angelegenheit anbieten und wir werden sehen, ob andere dies bestätigen. Alles, was ich unten schreibe, hat ein zugrunde liegendes "wie ich es sehe" -Thema und ist nicht maßgebend.
Der 80% Fall
Um Ihre Frage zu beantworten, sind Befehle in der Tat eine Punkt-zu-Punkt-Angelegenheit. Wenn ein Befehl in einen Controller (MVC-Webanwendung) eingeht, fordert dieser Controller einen Befehls-Dispatcher auf, einen und nur einen geeigneten Befehlshandler zu finden, und delegiert die Arbeit an diesen Handler.
Warum nicht veröffentlichen?
Es ist eine Frage der Verantwortung . Wenn etwas einen Befehl sendet, bedeutet dies die Erwartung, dass er erfüllt wird. Wenn Sie einfach veröffentlichen und hoffen, dass irgendwo etwas es aufnimmt und darauf reagiert, gibt es keine Garantie dafür, dass dies der Fall ist. Durch Extrapolation wissen Sie auch nicht, ob sich mehrere Handler nicht für einen Befehl entscheiden, was möglicherweise dazu führt, dass dieselbe Änderung mehr als einmal angewendet wird.
Ereignisse hingegen sind informativer Natur, und es ist vernünftig zu erwarten, dass null, zwei oder mehr Komponenten an einem bestimmten Ereignis interessiert sind. Es ist uns nicht wirklich wichtig, die angeforderte Änderung vorzunehmen.
Beispiel
Dies könnte mit dem wirklichen Leben verglichen werden. Wenn Sie drei Kinder haben, gehen Sie in ein Zimmer und rufen Sie einfach "Reinigen Sie das Badezimmer". Sie haben keine Garantie dafür, dass es jemand tut, und vielleicht, wenn es nicht zweimal gemacht wird (wenn Sie gehorsame Kinder haben ;-) Das sollten Sie Es geht Ihnen besser, wenn Sie einem bestimmten Kind das zuweisen, was Sie tun möchten.
Wenn das Kind seine Arbeit beendet hat, ist es jedoch praktisch, wenn es "Badezimmer wurde gereinigt" ruft, damit jeder, der sich die Zähne putzen möchte, weiß, dass er dies jetzt tun kann.
quelle
When a command enters a controller (MVC webapp)
-? Verwenden Sie RESTful? oder einige hybride API-Endpunkte? Könnten Sie bitte ein Beispiel hinzufügenexample.com/api/Post/AddPostComment
.Ich bin damit einverstanden, dass ein initiierendes System im Allgemeinen niemals erwarten würde, dass ein Befehl von mehreren Zielsystemen ausgeführt wird:
acknowledgement
und erfolgreichcompletion
oderfailure
können vom Zielsystem veröffentlicht werden, um den initiierenden Benutzer zu informieren System).Es ist jedoch immer noch sinnvoll, zusätzliche (nicht transaktionale und normalerweise recht "promiskuitive") Verbraucher zu abonnieren, die die zwischen Systemen ausgegebenen Befehle "belauschen"
quelle