CQRS + イベント ソーシング アーキテクチャを実装するさまざまなサンプル アプリケーションとフレームワークがあり、ほとんどの場合、イベント ハンドラーを使用して、イベント ストアに格納されたドメイン イベントから非正規化ビューを作成する方法について説明しています。
このアーキテクチャをホストする 1 つの例は、書き込み側へのコマンドを受け入れ、非正規化されたビューのクエリをサポートする Web API です。この Web API は、負荷分散されたファーム内の多くのマシンにスケールアウトされている可能性があります。
私の質問は、読み取りモデルのイベント ハンドラーがホストされている場所です。
考えられるシナリオ:
別のホスト上の単一の Windows サービスでホストされます。 もしそうなら、それは単一障害点を作成しませんか? これも展開を複雑にする可能性がありますが、単一スレッドの実行が保証されます。欠点は、読み取りモデルでレイテンシが増加する可能性があることです。
Web API 自体の一部としてホストされます。たとえば、イベント ストレージとイベント サブスクリプションの処理にEventStore を使用している場合、単一のイベントごとに複数のハンドラー (各 Web ファーム プロセスに 1 つ) が起動されるため、ハンドラーが読み取り/書き込みを試みるときに競合が発生します。彼らの読み取りストアに?それとも、特定の集約インスタンスについて、そのすべてのイベントがイベント バージョン順に一度に 1 つずつ処理されることが保証されていますか?
展開を簡素化し、イベントをリッスンする必要があるプロセス マネージャーもサポートするため、シナリオ 2 に傾倒しています。1 つのイベント ハンドラーのみが 1 つのイベントを処理する必要があるため、同じ状況です。
EventStore はこのシナリオを処理できますか? 最終的に一貫性のあるアーキテクチャで、他の人はイベントの処理をどのように処理していますか?
編集:
明確にするために、CQRS の「Q」のテーブルを読み取るのではなく、非正規化されたテーブルにイベント データを抽出するプロセスについて話しているのです。
私が探しているのは、イベントの処理が冪等の方法で処理されると仮定して、冗長性とスケールをサポートできる読み取りモデル/サガ/などのイベント処理をどのように実装および展開するかのオプションだと思います。
イベント ストアにイベントとして保存されたデータを処理するための 2 つの解決策を読みましたが、どちらを使用すべきかわかりません。
イベントバス
イベント バス/キューは、通常はリポジトリの実装によって、イベントが保存された後にメッセージを公開するために使用されます。読み取りモデルやサガ/プロセス マネージャーなどの利害関係者 (サブスクライバー) は、"何らかの方法で" バス/キューを使用して、べき等な方法で処理します。
キューが pub/sub である場合、これは、各ダウンストリームの依存関係 (読み取りモデル、saga など) が、キューをサブスクライブするためにそれぞれ 1 つのプロセスしかサポートできないことを意味します。複数のプロセスは、それぞれが同じイベントを処理し、下流で変更を行うために競合することを意味します。べき等処理は、一貫性/同時実行性の問題に対処する必要があります。
キューがコンシューマーと競合する場合、少なくとも、冗長性のために各 Web ファーム ノードでサブスクライバーをホストする可能性があります。ただし、これにはダウンストリームの依存関係ごとにキューが必要です。サガ/プロセス マネージャー用に 1 つ、読み取りモデルごとに 1 つなど、結果整合性のためにリポジトリはそれぞれに公開する必要があります。
購読/フィード
利害関係者 (サブスクライバー) がオンデマンドでイベント ストリームを読み取り、読み取りモデルに処理するために既知のチェックポイントからイベントを取得するサブスクリプション/フィード。
これは、必要に応じて読み取りモデルを再作成するのに最適です。ただし、通常の pub/sub パターンでは、ダウンストリームの依存関係ごとに 1 つのサブスクライバー プロセスのみを使用する必要があるように思われます。たとえば、各 Web ファーム ノードに 1 つずつ、同じイベント ストリームに複数のサブスクライバーを登録すると、それらはすべて、同じそれぞれの読み取りモデルを処理および更新しようとします。