3

現在、NServiceBus を使用して次の問題を解決する方法を調査しています。これでうさぎの穴に落ちないようにしたいだけです。

CQRS アーキテクチャに基づくソリューションがあります。基本的に、一連のコマンドが NServiceBus 経由でエンドポイントに配信されます。いくつかの処理を実行して集約ルートの状態を変更し、一連のイベントを起動してシステムの残りの部分に変更を通知します。

私が抱えている問題は、状態を変更している間に特定の集約ルートをロックすることを心配する必要がない 1 つのスレッドで、これがすべてうまく機能することです。

1 つのスレッドでは対応できないところまで来ているので、複数のワーカー スレッド/プロセスを使用してメッセージを処理する方法を検討する必要があります。

複数の集約ルートを同時に処理できるという事実に基づく自然なタスクの内訳がありますが、同じ集約ルートに対して複数のメッセージを同時に処理することはできません。メッセージが受信される速度。

特定の集約ルート ID をロックし、代わりに集約ルートをキュー/スレッド/プロセスに割り当てて、同じ集約ルートからのすべてのメッセージが同期的に処理されるようにする必要がある状況を回避しようとしています。

イベントを発行するために、NServiceBus で Pub/Sub モデルを使用しています。私が見る限りの問題は、メッセージの処理が別のエンドポイントに委任されている場合でも、これらのイベントを同じエンドポイントから発行する必要があることです。つまり、実際にはメッセージが「MyDomainQueue-Worker1」で処理されたときに、メッセージが「MyDomainQueue」から発行されたとシステムに認識させる必要があります。

私の計画は、メイン エンドポイントがメッセージの処理をワーカー エンドポイントに委任できるようにするカスタム ディストリビューターを作成することです。ディストリビューターは、ラウンド ロビン方式で任意の集約ルートにキューを割り当てます。メイン エンドポイントはこれらのワーカーにコマンドを送信し、処理が行われ、ワーカーはイベントのリストで応答します。その後、メイン エンドポイントはイベントをバスに発行します。

このアプローチに関するフィードバックを探しています。これを機能させるために少し苦労しているように感じます。他の誰かが同様の問題に対処したかどうかを確認したいだけです。おそらく、NServiceBus はその仕事に適したツールではないか、あるいは私のアプローチが単に間違っているのでしょう。あらゆるフィードバックを歓迎します。

ありがとう、

PS - 上記のソリューションに必要な構成の量についても懸念があります。

4

1 に答える 1

1

さまざまなエンドポイントからイベントを公開することに関して、1 つのサービスからイベントを公開するという概念にとらわれすぎていると思います。これは論理的な意味でのみ当てはまります。1 つのイベントは 1 つの論理サービスによって完全に所有される必要がありますが、論理サービスは多くのエンドポイントで構成される場合があります

イベントは実際にはキューから発行されません。イベントが発行されるキューについて考えるとき、実際に話しているのは、そのイベントのサブスクリプション要求を送信する入力キューです。

そのため、そのイベントのサブスクリプション リクエストがすべて同じ場所に送信される限り、複数のエンドポイントがすべて同じイベントを発行できます。

たとえば、2 つのエンドポイントが同じコマンドを処理する (そして同じイベントを発行する) 場合、一方は長い SLA のバルクであり、もう一方ははるかに短い SLA です。 SLA - 大口顧客であるか、応答を待っている実際の人間のユーザーからコマンドが送信されている可能性があります。QueueA と PriorityQueueA は両方とも同じコマンドを処理し、同じイベントを発行しますが、QueueA がサブスクリプションを処理するため、両方のプロセスが QueueA から「発行」します。

そうは言っても、複数のスレッドが集約ルートにアクセスできるようにしてみましたか? 多少の競合があっても、再試行回数が少ないと、思ったほど競合しない場合があります。NServiceBus を使用してかなり論争の多いプロセスが実稼働環境にあり、ログに例外として競合の証拠が時折見られますが、5 回の再試行でエラー キューに進むことはありません。

-- 最近では、第 2 レベルの再試行機能が追加され、メッセージがエラー キューで終わる可能性がさらに減少しました。

それほど多くの競合がある場合、別の戦略として、現在操作されている集計ルートのメモリ内リストを維持し、「ロックアウト」する必要があるメッセージが着信した場合は、Bus.HandleCurrentMessageLater()そのメッセージを最後に貼り付けるように呼び出すだけです。キューの。

于 2012-07-08T04:53:47.597 に答える