1 日を通して負荷が高いキューがあるとします。キュー内の各メッセージの処理には数秒かかります。
4 台のマシンがすべて外部アクティベーターでセットアップされている場合 (すべて同じキュー/サービス用に構成されている)、それは機能しますか?
機能する場合、ロード バランスをとりますか (作業をワーカー マシン全体に均等に分散しますか)。
1 日を通して負荷が高いキューがあるとします。キュー内の各メッセージの処理には数秒かかります。
4 台のマシンがすべて外部アクティベーターでセットアップされている場合 (すべて同じキュー/サービス用に構成されている)、それは機能しますか?
機能する場合、ロード バランスをとりますか (作業をワーカー マシン全体に均等に分散しますか)。
これは、最終的には、保留中の複数のWAITFOR (RECEIVE)
ステートメントがどのように処理されるかにかかっています。アプリの 4 つのインスタンスが実行されており、それぞれがWAITFOR(RECEIVE)
. メッセージがキューで使用可能になります。問題は、保留中の WAITFOR(RECEIVE) のどれがメッセージを取得するかということです。
答えは多くの人を驚かせますが、これは設計によるものであり、最後に発行された WAITFOR(RECEIVE) はメッセージを受け取ります。最も古いものでも、ランダムなものでもなく、最新のものです。つまり、リスナーの LIFO 順序です。
なんで?この動作は意図的なものであり、負荷を処理するために必要な数のリスナーを持つことを目的としています。もともと4つのプロセスがリッスンしています。メッセージを取得して処理し、再び を発行することでWAITFOR(RECEIVE)
、さらに多くのメッセージをリッスンし始めます。次のメッセージが到着すると、決定論的に同じプロセスに渡されます。これは、最近発行された WAITFOR(RECEIVE) であるためです。このリスナーは、メッセージを取得して処理し、再度 WAITFOR(RECEIVE) を発行します。そして、再び、決定論的に次のメッセージを取得します。要点は次のとおりです。この単一のリスナーがすべての着信トラフィックを処理できる場合、他の 3 つは冗長です。しばらくすると、保留中の WAITFOR(RECEIVE) がタイムアウトになり、これらのプロセスは安全に終了 (終了) します。
2 番目のプロセスは、最初のリスナーが別のメッセージの処理でビジー状態(つまり、新しい WAITFOR(RECEIVE) をポストしていない) の間にメッセージが到着した (使用可能になった) 場合にのみ、メッセージを取得できます。
では、なぜこれが良いのでしょうか?パズルのピースがもう 1 つあります。それは、アクティブ化が発生するタイミングを理解することです。単独の処理スレッドが着信トラフィックを処理できなくなった場合、構成された MAX_QUEUE_READERS まで、新しい処理スレッド (内部または外部) が生成されます。
これで、これら 2 つの動作の間で、自己調整された最適なリーダー (プロセス、スレッド) の数が得られます。
相関メッセージ ロック ( Conversation Group Locks ) により、キューにメッセージが含まれる場合がありますが、新しいスレッドで処理できるメッセージがない (つまり、すべてロックされている) ことに注意してください。アクティブ化/待機の目的で、この状況はキューが「空」であることを意味します (新しいプロセッサで使用できるメッセージはありません)。
最後に、これらすべてを実現するには、アプリケーションが正しく動作する必要があります。
組み込みの負荷分散を利用するには、サービスを複数の SQL Server インスタンスに展開する必要があります。それはあなたが計画しているものとはかなり違うのではないかと思うので、外部のアクティブ化プロセスが見る 4 つのキューの 1 つに到着したメッセージを転送する内部アクティブ化プロシージャを用意するなど、独自の方法を考え出す必要があります。