適用対象:SQL Server
Azure SQL Managed Instance
Service Broker アクティブ化処理は、次の 2 段階で構成されています。 まず、アクティブ化が必要かどうかを Service Broker が決定します。 次に、アクティブ化が発生したかどうかを Service Broker が確認します。 内部アクティブ化と外部アクティブ化では厳密な処理は異なりますが、使用されている全体的な概念はどちらの方式も同一です。
アクティブ化が必要かどうかを判断する
有用な作業が発生し、それを新しいキュー リーダーで実行する場合、常にアクティブ化が必要です。 キュー モニターでは、アクティブ化が必要かどうかが判断されます。 Service Broker は、アクティブ化 STATUS = ON
または QUEUE_ACTIVATION
イベント通知が登録されているキューごとにキュー モニターを作成します。 動的管理ビュー sys.dm_broker_queue_monitors には、インスタンスでアクティブなキュー モニターが一覧表示されます。
各キュー モニターは、次の条件を追跡します。
- キューに受信の準備ができているメッセージが含まれているかどうか。
- キューで
RECEIVE
ステートメントが空の結果セットを返したのはどれくらい最近のことですか? - キューで現在実行中のアクティブ化ストアド プロシージャの数
キュー モニターでは、数秒ごと、または次のいずれかの事象が発生したときに、アクティブ化が必要かどうかを調べます。
- 新しいメッセージがキューに配信されたとき。
- SQL Server は、キューの
RECEIVE
ステートメントを実行します。 -
RECEIVE
ステートメントを含むトランザクションがロールバックされます。 - キュー モニターから開始したすべてのストアド プロシージャが終了したとき。
- SQL Server は、キューの
ALTER
ステートメントを実行します。
次のいずれかの条件に該当する場合は、アクティブ化が必要です。
未読のメッセージを含んでいないキューに新しいメッセージが配信され、そのキューでアクティブ化ストアド プロシージャが実行されていない場合。
キューに未読のメッセージが含まれています。
GET CONVERSATION GROUP
ステートメントまたはRECEIVE
句のないWHERE
ステートメントで待機しているセッションはなく、GET CONVERSATION GROUP
句のないRECEIVE
ステートメントまたはWHERE
ステートメントは数秒間空の結果セットを返しません。 つまり、アクティブなストアド プロシージャがメッセージを十分な速度で読み取ることができず、キューに蓄積されている場合。
この処理手順により、キューを処理しているキュー リーダーの数がメッセージの着信トラフィックに伴って増加しているかどうかをキュー モニターで判断できます。 この方法では、会話グループのロックが考慮されます。 一度に 1 つのキュー リーダーでしかメッセージ交換のメッセージを処理できないので、キュー内の未読メッセージの数などの単純なしくみに反応してキュー リーダーを起動すると、リソースを浪費する可能性があります。 代わりに、Service Broker のアクティブ化では、新しいキュー リーダーに役立つ作業があるかどうかを考慮します。
たとえば、キューには、1 つの会話に大量の未処理のメッセージが含まれている場合があります。 ただし、1 つのキュー リーダーでしかメッセージを処理できません。 ここで、別のキュー リーダーがアクティブ化されると、 2 番目のキュー リーダーは、すべてのメッセージが 1 つの会話に属しているため、 RECEIVE
ステートメントで待機します。 キュー内のすべてのメッセージが同じメッセージ交換に属し、2 番目のキュー リーダーが実行されたままである限り、キュー モニターは別のキュー リーダーを起動しません。
アクティブ化が行われるかどうかを判断する
Service Broker により、アクティベーションが必要であると判断されると、Service Broker はアクティベーションを行うかどうかを決定する必要があります。
内部アクティブ化の場合、実行中のプログラムの数がキューに設定されている MAX_QUEUE_READERS
値より少ない場合、キュー モニターはアクティブ化ストアド プロシージャの新しいインスタンスをアクティブ化します。 実行中のプログラムの数が MAX_QUEUE_READERS
値以上の場合、キュー モニターはストアド プロシージャの新しいインスタンスを開始しません。 管理ビュー sys.dm_broker_activated_tasks には、Service Broker によって開始されたストアド プロシージャに関する情報が含まれています。
外部アプリケーションの場合、Service Broker には、キューを操作している可能性がある個別のキュー リーダーの数に関する情報はありません。 さらに、アクティブ化イベントが発生してからリーダーがキューの読み取りを開始するまでの間に、何らかの起動時間が必要になる場合があります。 そのため、Service Broker は外部アプリケーションが応答するためのタイムアウトを提供します。 タイムアウト中、Service Broker は別の通知を生成しません。 アプリケーションがキューで RECEIVE
を呼び出すか、タイムアウトが切れると、アクティブ化が必要な場合は、Service Broker によって別のイベント通知が作成されます。 外部アプリケーションでイベント通知を監視すると同時に、プログラムを実行してイベントを読み取るためにキュー リーダーを増やす必要があるかどうかを判断します。