16

私は Sql Server Service Broker の初心者であり、Service Broker を (一見) 単純なユース ケースに設定するための最良の方法を把握しようとしています。1 つのアプリケーションが作業項目を別のアプリケーションがそのキューから作業項目を取得して処理します。最初のアプリケーションが 2 番目のアプリケーションからステータス メッセージを取得する必要はありません。キューを単一の Sql Server インスタンスに配置したい。

私を最も混乱させているのは、会話/ダイアログがこの状況にどのように関係しているかです。会話/ダイアログのコンテキストでのみメッセージを送受信できることは知っていますが、2 つのアプリケーション間でやり取りがないため、いつ新しい会話を作成するのが適切なのか迷っています。2つの極端な選択肢は次のようです。

  • 作業項目をキューに入れるたびに、新しい会話を開始します。そのため、各会話には 1 つのメッセージしか含まれません。
  • 展開時に、1 つの無期限の会話を手動で作成します。作業項目をキューに入れるときは、常にその単一の会話の一部として送信します。

これらのルートのいずれかを選択すると、どのような結果になるでしょうか?

また、最初のケースでは、Sql Server がリソースを内部的にクリーンアップできるようにするために、いくつかの END CONVERSATION を実行する必要があるようです。これらをいつ配置するのが正しいかについてのガイダンスはありますか? (または、最終的には会話がタイムアウトになることに依存する方が良い可能性があるでしょうか?)

4

2 に答える 2

27

それぞれの作業項目から、それぞれの会話を開始する必要があります。プロデューサ (イニシエータ) はダイアログを開始し、作業項目を説明するメッセージを送信してからコミットします。コンシューマー (ターゲット) はメッセージを受信 (またはアクティブ化) し、ペイロードを調べて作業項目の詳細を理解し、作業を実行してから、ダイアログを終了してコミットします。結果として得られる EndDialog メッセージは、イニシエーター サービス キューに送り返され、イニシエーター キューでアクティブ化されたプロシージャは、イニシエーター側でダイアログを終了することによって応答します。

これは最も単純な展開であり、それを起動して実行すると、構築するための健全な基盤が確保されます。プロデューサがワークアイテムをエンキューしたときからイニシエータ側で手抜きをしてダイアログを終了しないでください。これはファイア アンド フォーゲットであり、いくつかの欠点があります。

高いパフォーマンス要件 (1 秒あたり 200 リクエスト以上) がある場合は、会話をより明示的に管理し始める必要があります。パフォーマンス上の理由からの会話の再利用に関するブログ エントリがあります。受信側では、Writing Service Broker Proceduresを読むことをお勧めします。

作業項目をスケジュールするのではなく、代わりにカスタム プロシージャを起動しますが、必要なことをほぼ実行するブログ エントリもあります: Asynchronous procedure execution

アクティブ化されたコンテキストから作業項目を消費することを決定し、アクティブ化の優れたセルフ バランシング機能を活用する場合は、アクティブ化が発生する EXECUTE AS コンテキストを理解する必要があります。

于 2009-08-12T03:00:20.000 に答える
9

Remus の回答はとても気に入っていますが、すべての作業項目を 1 つの会話にまとめるよりも、作業項目ごとに個別の会話を開始するほうがよい理由については特に触れていません。これに関連する 2 つの注意事項:

まず、すべての作業項目を 1 つの会話に入れると、作業項目を処理する複数のスレッド/プロセスがある場合、同時実行の問題が発生する可能性があります。Service Broker ワーカー プロセスは、次のようになります (疑似コード)。

begin transaction
receive top n work items from queue
process work items
commit transaction

(作業項目が正常に処理されるまでコミットしないことで、たとえば、プロセスが停止した場合に、受け取ったがまだ処理されていない作業項目がキューから削除されないようにすることができます。)

各 RECEIVE コマンドが、RECEIVE されたものと同じ会話 (または会話グループ) を共有するキュー内のすべてのメッセージに対して排他的読み取りロックを取得するように Service Broker がプログラムされているため、同時実行の問題が発生します。そのロックは、トランザクションがコミットされるまで保持されます。( Conversation Group Locksを参照してください。) したがって、キュー内のすべての作業項目が 1 つの会話内にある場合、1 つのワーカー プロセスが「作業項目の処理」ステップにある間は、他のワーカー プロセスが作業を行うことはできません。

多くの項目を 1 つの会話に入れることの 2 つ目の問題は、特定のエラー状態で失われたり再処理しなければならない作業項目の量が増えることです。これを適切に説明するには、レムスに任せます。彼のRecycling Conversationsを参照してください。特に、「1 つのダイアログを再利用してすべてのメッセージを送信することは [...] すべての卵を 1 つのバスケットに入れるようなものです」と述べている部分を参照してください。これらのエラー状況の一部から回復できる場合もありますが、コードがより複雑になる可能性があります。

すべての作業項目に対して単一の会話を使用することに反対するいくつかの議論があると思われますが、私はそれらに精通していません。

これは、すべての作業項目ごとに個別の会話を開始することが常に正しい解決策であると言っているわけではありません。しかし、Remus の投稿を読んだ後では、彼のアドバイスは適切に思えます。会話ごとに 1 つの作業項目から始めて、必要に応じて複雑さを追加します。(しかし、すべてのメッセージを 1 つの会話に入れるという極端な方法は、おそらく絶対にすべきではありません。)

于 2009-08-15T22:40:47.683 に答える