2

システムの設計上の問題を解決するためのアイデア/パターンを探しています。まもなく作業を開始します。システムの特定の領域間で通信するために、ある種のメッセージング(おそらくMSMQ)を使用する必要があることは間違いありません。車輪の再発明はしたくありませんが、同時に、仕事に適したツールを使用していることを確認したいと思います。私はNServiceBusをいじくり回して読んでいて、それが何をするのか非常に感銘を受けていますが、それが私が達成しようとしていることを意図しているのかどうかはわかりません。

これは、システムが実行する必要があることの(うまくいけば)非常に単純で概念的な説明です。

クライアントがメッセージを送信できるサービスがあります。サービスは「ファイアアンドフォーゲット」です。クライアントが返す可能性が最も高いのは、成功または失敗を示す可能性のあるものです(成功とはメッセージが受信されたことです)。

各メッセージの処理/処理は重要であり、かなりのシステムリソースを消費する可能性があります。このため、同時に処理できるのはXメッセージのみです。Xは構成可能な値です(システム仕様などに基づく)。着信メッセージは、処理される「順番」になるまでキューに保存されます。

クライアントごとに、メッセージを順番に処理する必要があります(FIFO)。ただし、一部のクライアントは、たとえば一定期間接続が失われた場合など、多数のメッセージを連続して(数千以上)送信する場合があります。このため、メッセージはクライアント間でラウンドロビン方式で処理する必要があります。つまり、クライアントがゴージしたり、飢えたりすることはできません。したがって、システムは特定のクライアントのキューを照会するか、クライアントごとに個別のキューを作成して(コンパイル時にクライアントが認識されないため、自動的に)、それらから順番にプルする必要があります。

私の現在の考えは、実際にはバニラMSMQを使用し、メッセージを受け入れて1つ以上のキューに書き込むサービスを作成し、キューからメッセージを読み取って処理/処理するプロセスを作成する必要があるということです。ただし、NServicebusのようなもので得られる信頼性、監査、拡張性、および構成の容易さは非常に魅力的に見えます。

ESBはその仕事にとって間違ったツールですか?私が見なければならない他の技術やパターンはありますか?

アップデート

いくつかの説明。

「順番に」メッセージを処理することに関して-単一のクライアントのコンテキストでは、メッセージは受信された順序で絶対に処理される必要があります。正確な理由を説明するのは複雑ですが、これは確固たる要件です。クライアントごとに1つのメッセージだけが同時に処理されることになると言うのを怠りました。したがって、10個のワーカースレッドがあり、処理を待機しているメッセージが1つのクライアントだけであったとしても、一度に処理されるのはそれらのメッセージの1つだけであり、競合状態の心配はありません。

これは一般的にバニラMSMQで可能であると思います。つまり、メッセージのリストをキューに入れて、常に最も古いものを最初に取得することができます。

また、ラウンドロビン注文のユースケースを明確にしたいと思いました。この例では、メッセージを送信する2つのクライアント(AとB)と、1つのワーカースレッドしかありません。すべてのキューが空です。クライアントAは一晩で接続を失ったため、午前8時にサービスに1000件のメッセージを送信します。これらのメッセージはキューに入れられ、ワーカースレッドは最も古いメッセージを取得して処理を開始します。この最初のメッセージが処理されている間、クライアントBはメッセージをサービスに送信します。サービスはキューに入れられます(前述のように、おそらく別のキューにあります)。クライアントAの最初のメッセージの処理が完了すると、ロジックはクライアントBにメッセージがあるかどうか(クライアントBの「ターン」)をチェックし、メッセージが見つかったので次に処理する必要があります。

その間にクライアントBがメッセージを送信しなかった場合、ワーカーはクライアントAのメッセージを一度に1つずつ処理し続け、処理後に常に他のクライアントキューに待機中のメッセージが含まれているかどうかを確認して、クライアントが不足していないことを確認します。

ESBとこの問題の間に不一致があるかもしれないと私がまだ感じているのは、ESBがサービス間の通信を容易にするように設計されていることです。私が達成しようとしているのは、メッセージング/通信と選択的キューイングシステムの組み合わせです。

4

2 に答える 2

2

NServiceBusのようなESBを使用することは、問題の良い解決策のようです。しかし、あなたの概念的な説明に基づいて、考慮すべきことがいくつかあります。可能なESBソリューションとしてNServiceBusを使用して、要件を段階的に見ていきましょう。

クライアントがメッセージを送信できるサービスがあります。サービスは「ファイアアンドフォーゲット」です。クライアントが返す可能性が最も高いのは、成功または失敗を示す可能性のあるものです(成功とはメッセージが受信されたことです)。

これは、NServiceBusを使用して簡単に実行できます。クライアントからBus.Send(Message)を実行できます。クライアントが回答を必要とする場合は、Bus.Return(ErrorCode)を使用できます。あなたは「メッセージが受信されたことで成功した」と述べています。NServiceBusのようなESBを使用する場合、メッセージを配信するのはメッセージングプラットフォーム次第です。したがって、Bus.Sendが例外をスローしない場合は、メッセージが正しく送信されたことを確認できます。このため、成功/失敗のメッセージをクライアントに送り返す必要はおそらくありません。

各メッセージの処理/処理は重要であり、かなりのシステムリソースを消費する可能性があります。このため、同時に処理できるのはXメッセージのみです。Xは構成可能な値です(システム仕様などに基づく)。着信メッセージは、処理される「順番」になるまでキューに保存されます。

NServiceBusを使用する場合、「NumberOfWorkerThreads」オプションを設定することにより、ワーカースレッドの数を構成できます。サーバーに複数のコア/CPUがある場合は、この設定を使用して作業負荷のバランスをとることができます。

クライアントごとに、メッセージを順番に処理する必要があります(FIFO)。

これは、要件によっては問題を引き起こす可能性があるものです。ESBは一般に、メッセージを処理するスレッドが多数ある場合、メッセージを順番に処理することを約束しません。NServiceBusの場合、クライアントからバスに一連のメッセージを送信でき、これらは順番に処理されます。また、 Sagasを使用することで、順序どおりのメッセージングの問題のいくつかを解決できます。

ただし、一部のクライアントは、たとえば一定期間接続が失われた場合など、多数のメッセージを連続して(数千以上)送信する場合があります。

ESBソリューションを使用する場合、クライアントが機能するためにサーバーが稼働している必要はありません。クライアントは引き続きメッセージを送信でき、サーバーはオンラインに戻るとすぐにメッセージの処理を開始します。これについての簡単な紹介です。

このため、メッセージはクライアント間でラウンドロビン方式で処理する必要があります。つまり、クライアントがゴージしたり、飢えたりすることはできません。

メッセージを使用することにしたので、これは問題ではありません:)

したがって、システムは特定のクライアントのキューを照会するか、クライアントごとに個別のキューを作成して(コンパイル時にクライアントが認識されないため、自動的に)、それらから順番にプルする必要があります。

これについて詳しく教えていただけますか?これについてのあなたのデザインはよくわかりません。

于 2010-08-23T05:28:18.220 に答える
2

したがって、システムは特定のクライアントのキューを照会できる必要があります。

カーソルを使用して特定のクライアントからのメッセージをMSMQキューで検索することは非効率的であり、拡張性がありません。

または、クライアントごとに個別のキューを作成し(コンパイル時にクライアントが認識されないため、自動的に)、ローテーションでそれらからプルします。

MSMQはキューを自動的に作成できません。すべてのメッセージは、最初に既知のキューに送信する必要があります。ただし、独自のカスタムディスパッチャサービスは、オンデマンドで新しいキューを作成し、それらにメッセージのコピーを配置することができます。

[[アプリケーションコードではできないので、「移動」メッセージを言うのは避けます。メッセージを読み取って、元のデータを使用して新しいメッセージを作成することしかできません。この区別は、たとえばソースジャーナリングを使用している場合に重要です。]]

乾杯

ジョン・ブレイクウェル

于 2010-08-23T10:08:50.703 に答える