アクティブ化が行われるタイミングについて

Service Broker のアクティブ化処理は 2 段階で行われます。まず、Service Broker で、アクティブ化が必要かどうかを判断します。次に、Service Broker で、アクティブ化を行うかどうかを判断します。内部アクティブ化と外部アクティブ化では厳密な処理は異なりますが、使用されている全体的な概念はどちらの方式も同一です。

アクティブ化が必要かどうかの判断

有用な作業が発生し、それを新しいキュー リーダーで実行する場合、常にアクティブ化が必要です。アクティブ化が必要かどうかは、キュー モニタで判断されます。Service Broker では、アクティブ化が STATUS = ON のキューごと、または QUEUE_ACTIVATION イベント通知が登録されているキューごとに、キュー モニタが作成されます。インスタンス内でアクティブになっているキュー モニタは、動的管理ビュー (「sys.dm_broker_queue_monitors (Transact-SQL)」参照) に一覧表示されます。各キュー モニタでは、次の内容が追跡されます。

受信準備ができたメッセージがキューに格納されているかどうか

キューで実行した RECEIVE ステートメントが最後に空の結果セットを返してからの時間

キューで現在実行中のアクティブ化ストアド プロシージャの数

キュー モニタでは、数秒ごと、または次のいずれかの事象が発生したときに、アクティブ化が必要かどうかを調べます。

  • 新しいメッセージがキューに配信されたとき。

  • SQL Server によりキューに対して RECEIVE ステートメントが実行されたとき。

  • RECEIVE ステートメントを含むトランザクションがロールバックされたとき。

  • キュー モニタから開始したすべてのストアド プロシージャが終了したとき。

  • SQL Server によりキューに対して ALTER ステートメントが実行されたとき。

次のいずれかの条件に該当する場合、アクティブ化が必要です。

  • 未読のメッセージを含んでいないキューに新しいメッセージが配信され、そのキューでアクティブ化ストアド プロシージャが実行されていない場合。

  • キューに未読のメッセージが含まれておらず、GET CONVERSATION GROUP ステートメントまたは WHERE 句を使用しない RECEIVE ステートメントで待機しているセッションがなく、かつ数秒前から空の結果セットを返した GET CONVERSATION GROUP ステートメントまたは WHERE 句を使用しない RECEIVE ステートメントがない場合。つまり、アクティブなストアド プロシージャがメッセージを十分な速度で読み取ることができないために、メッセージが蓄積されている場合。

この処理手順により、キューを処理しているキュー リーダーの数がメッセージの着信トラフィックに伴って増加しているかどうかをキュー モニタで判断できます。この方式は、メッセージ交換グループのロックを考慮に入れています。一度に 1 つのキュー リーダーでしかメッセージ交換のメッセージを処理できないので、キュー内の未読メッセージの数などの単純なしくみに反応してキュー リーダーを起動すると、リソースを浪費する可能性があります。代わりに Service Broker のアクティブ化では、新しいキュー リーダーで有用な作業を行うかどうかが考慮されます。

たとえば、1 回のメッセージ交換についての未処理のメッセージが大量にキューにあるとします。ただし、1 つのキュー リーダーでしかメッセージを処理できません。ここで、別のキュー リーダーがアクティブ化されると、すべてのメッセージが 1 つのメッセージ交換に属しているので、2 番目のキュー リーダーは RECEIVE ステートメントで待機します。キュー内のすべてのメッセージが同一のメッセージ交換に属していて、2 番目のキュー リーダーが実行状態である間は、別のキュー リーダーが起動されることはありません。

アクティブ化を行うかどうかの判断

Service Broker でアクティブ化が必要であると判断したら、Service Broker はアクティブ化を行うかどうかを決定する必要があります。

内部アプリケーションでは、実行中のプログラムの数がキューの MAX_QUEUE_READERS 値より少ない場合、アクティブ化ストアド プロシージャの新しいインスタンスがアクティブ化されます。実行中のプログラムの数が MAX_QUEUE_READERS 値以上である場合、新しいインスタンスは起動されません。管理ビュー sys.dm_broker_activated_tasks (Transact-SQL) には、Service Broker から起動したストアド プロシージャの情報が表示されます。

外部アプリケーションの場合、キューで機能していると見られるキュー リーダーの数を Service Broker では把握できません。さらに、アクティブ化イベントが発生してからキュー リーダーがキューの読み取りを開始するまでに起動時間が必要になる可能性もあります。そこで、Service Broker は外部アプリケーションが応答するまでタイムアウトします。その間、Service Broker は別の通知を生成しません。アプリケーションがキューの RECEIVE を呼び出すか、タイムアウトが発生した後は、アクティブ化が必要になった場合に Service Broker によって別のイベント通知が生成されます。外部アプリケーションでイベント通知を監視すると同時に、プログラムを実行してイベントを読み取るためにキュー リーダーを増やす必要があるかどうかを判断します。