アクティブ化が行われるタイミングについて
Service Broker のアクティブ化処理は、2 つの段階に分かれています。まず、アクティブ化が必要かどうかを判断します。次に、アクティブ化を行うかどうかを判断します。内部アクティブ化と外部アクティブ化では厳密な処理は異なりますが、使用されている全体的な概念はどちらの方式も同一です。
アクティブ化が必要かどうかの判断
有用な作業が発生し、それを新しいキュー リーダーで実行する場合、常にアクティブ化が必要です。アクティブ化が必要かどうかは、キュー モニタで判断されます。Service Broker では、アクティブ化が STATUS = ON のキューごと、または QUEUE_ACTIVATION イベント通知が登録されているキューごとに、キュー モニタが作成されます。インスタンス内でアクティブになっているキュー モニタは、動的管理ビュー sys.dm_broker_queue_monitors に一覧表示されます。各キュー モニタで追跡される内容は、受信準備ができたメッセージがキューに含まれているかどうか、キューで実行した 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 番目のキュー リーダーが実行状態である間は、別のキュー リーダーが起動されることはありません。
アクティブ化を行うかどうかの判断
アクティブ化が必要であると判断したら、アクティブ化を行うかどうかを判断する必要があります。
内部アプリケーションでは、実行中のプログラムの数がキューの MAX_QUEUE_READERS 値より少ない場合、アクティブ化ストアド プロシージャの新しいインスタンスがアクティブ化されます。実行中のプログラムの数が MAX_QUEUE_READERS 値以上である場合、新しいインスタンスは起動されません。管理ビュー sys.dm_broker_activated_tasks には、Service Broker から起動したストアド プロシージャの情報が表示されます。
外部アプリケーションの場合、キューで機能していると見られるキュー リーダーの数を Service Broker で把握できません。さらに、アクティブ化イベントが発生してからキュー リーダーがキューの読み取りを開始するまでに起動時間が必要になる可能性もあります。したがって、外部アプリケーションが応答するまでに中断が発生します。その間は別の通知が生成されません。アプリケーションがキューの RECEIVE を呼び出すか、中断が終了した後は、アクティブ化が必要になった場合に別のイベント通知が生成されます。外部アプリケーションでイベント通知を監視すると同時に、プログラムを実行してイベントを読み取るためにキュー リーダーを増やす必要があるかどうかを判断します。
参照
その他の技術情報
CREATE QUEUE (Transact-SQL)
アクティブ化ストアド プロシージャのトラブルシューティング