Azure Service Bus メッセージのプリフェッチPrefetch Azure Service Bus messages

公式の Service Bus クライアントでプリフェッチを有効にしていると、受信側は、アプリケーションが元々要求した数を超えて PrefetchCount 限界に達するまでメッセージを自動的に取得します。When Prefetch is enabled in any of the official Service Bus clients, the receiver quietly acquires more messages, up to the PrefetchCount limit, beyond what the application initially asked for.

このため、Receive または ReceiveAsync を 1 回呼び出すと、使用の準備ができると同時にメッセージが返され、すぐに使用できます。A single initial Receive or ReceiveAsync call therefore acquires a message for immediate consumption that is returned as soon as available. クライアントは、プリフェッチ バッファーが満杯になるまで、バック グラウンドでメッセージを取得し続けます。The client then acquires further messages in the background, to fill the prefetch buffer.

プリフェッチの有効化Enable prefetch

.NET では、MessageReceiverQueueClient または SubscriptionClientPrefetchCount のプロパティを 0 より大きい数値に設定することでプリフェッチ機能を有効化します。With .NET, you enable the Prefetch feature by setting the PrefetchCount property of a MessageReceiver, QueueClient, or SubscriptionClient to a number greater than zero. 値を 0 に設定すると、プリフェッチが解除されます。Setting the value to zero turns off prefetch.

この設定は、QueuesGettingStarted または ReceiveLoop サンプルの設定の受信側に簡単に追加することができ、これらのコンテキストでの効果を確認できます。You can easily add this setting to the receive-side of the QueuesGettingStarted or ReceiveLoop samples' settings to see the effect in those contexts.

メッセージがプリフェッチ バッファーにある間は、その後の Receive/ReceiveAsync 呼び出しはバッファーから満たされ、スペースが空くとバックグラウンドでバッファに補充されます。While messages are available in the prefetch buffer, any subsequent Receive/ReceiveAsync calls are immediately fulfilled from the buffer, and the buffer is replenished in the background as space becomes available. 配信するメッセージがない場合は、受信操作によってバッファーが空になり、想定どおり、ブロックを待機します。If there are no messages available for delivery, the receive operation empties the buffer and then waits or blocks, as expected.

プリフェッチも、OnMessage および OnMessageAsync API で同様に機能します。Prefetch also works in the same way with the OnMessage and OnMessageAsync APIs.

プリフェッチの方が速度が速いのに既定のオプションではない理由If it is faster, why is Prefetch not the default option?

プリフェッチは、アプリケーションが要求する前にローカルで取得できるようメッセージを用意することによって、メッセージ フローを高速化します。Prefetch speeds up the message flow by having a message readily available for local retrieval when and before the application asks for one. このスループットの向上は、以下のメリットとデメリットを比較したうえで、アプリケーションの作成者がその使用を明示的に決定した結果として得られるものです。This throughput gain is the result of a trade-off that the application author must make explicitly:

ReceiveAndDelete 受信モードでは、プリフェッチ バッファーに取得されたすべてのメッセージはキューで使用できなくなり、Receive/ReceiveAsync または OnMessage/OnMessageAsync API を通して アプリケーションで受信されるまで、メモリ内のプリフェッチ バッファーにのみ存在します。With the ReceiveAndDelete receive mode, all messages that are acquired into the prefetch buffer are no longer available in the queue, and only reside in the in-memory prefetch buffer until they are received into the application through the Receive/ReceiveAsync or OnMessage/OnMessageAsync APIs. アプリケーションがメッセージを受信する前に終了すると、それらのメッセージは失われ、復元できなくなります。If the application terminates before the messages are received into the application, those messages are irrecoverably lost.

PeekLock 受信モードでは、メッセージはロック状態のプリフェッチ バッファーにフェッチされ、ロックの有効期限のためのタイムアウト クロックが設定されます。In the PeekLock receive mode, messages fetched into the Prefetch buffer are acquired into the buffer in a locked state, and have the timeout clock for the lock ticking. プリフェッチ バッファーのサイズが大きく、処理に時間がかかるため、メッセージがプリフェッチ バッファー内にある間、あるいはアプリケーションがメッセージを処理している間にメッセージのロックの有効期限が切れると、アプリケーションが処理について混乱するイベントが発生する可能性があります。If the prefetch buffer is large, and processing takes so long that message locks expire while residing in the prefetch buffer or even while the application is processing the message, there might be some confusing events for the application to handle.

アプリケーションは、期限が切れた、またはロックの有効期限がもうすぐ切れるメッセージを取得する場合があります。The application might acquire a message with an expired or imminently expiring lock. この場合、アプリケーションはメッセージを処理する可能性がありますが、ロックの有効期限のために完了できません。If so, the application might process the message, but then find that it cannot complete it due to a lock expiration. アプリケーションは LockedUntilUtc プロパティ (ブローカーとローカル コンピューターのクロックのずれによって規定されます) をチェックします。The application can check the LockedUntilUtc property (which is subject to clock skew between the broker and local machine clock). メッセージのロックの有効期限が切れている場合は、アプリケーションはメッセージを無視する必要があり、メッセージに対する、またはメッセージによる API 呼び出しは行われません。If the message lock has expired, the application must ignore the message; no API call on or with the message should be made. メッセージの期限が切れていないが有効期限が近づいている場合は、message.RenewLock() を呼び出すことにより、既定のロック期間 1 回分までロックを更新および拡張できます。If the message is not expired but expiration is imminent, the lock can be renewed and extended by another default lock period by calling message.RenewLock()

プリフェッチ バッファーでロックの有効期限が自動的に切れると、メッセージは破棄済みとして扱われ、もう一度キューから取得できるようになります。If the lock silently expires in the prefetch buffer, the message is treated as abandoned and is again made available for retrieval from the queue. それにより、プリフェッチ バッファーにフェッチされ、末尾に配置される場合があります。That might cause it to be fetched into the prefetch buffer; placed at the end. メッセージの有効期限中、プリフェッチ バッファーが通常通り処理されない場合は、メッセージのプリフェッチが繰り返されますが、使用可能な (ロックが有効) 状態で効果的に配信されることはなく、最終的には、最大配信回数を超えて配信不能キューに入れられます。If the prefetch buffer cannot usually be worked through during the message expiration, this causes messages to be repeatedly prefetched but never effectively delivered in a usable (validly locked) state, and are eventually moved to the dead-letter queue once the maximum delivery count is exceeded.

高い信頼性でメッセージを処理する必要がある場合は、処理に工数と時間がかかるため、プリフェッチ機能をまったく使用しないか、慎重に使用することをお勧めします。If you need a high degree of reliability for message processing, and processing takes significant work and time, it is recommended that you use the prefetch feature conservatively, or not at all.

高いスループットを必要としており、メッセージ処理が一般に安価である場合は、プリフェッチによって大きなスループットの利点がもたらされます。If you need high throughput and message processing is commonly cheap, prefetch yields significant throughput benefits.

最大プリフェッチ数とキューまたはサブスクリプションに構成されているロック期間は、ロックのタイムアウトが、プリフェッチ バッファーの最大サイズに 1 メッセージ分を足した累計予想メッセージ処理時間以上になるようにバランスを調整する必要があります。The maximum prefetch count and the lock duration configured on the queue or subscription need to be balanced such that the lock timeout at least exceeds the cumulative expected message processing time for the maximum size of the prefetch buffer, plus one message. 同時に、ロック タイムアウトは、メッセージが誤って破棄された場合に、再配信される前にロックの有効期限が切れないよう、その最大 TimeToLive を超えない長さである必要があります。At the same time, the lock timeout ought not to be so long that messages can exceed their maximum TimeToLive when they are accidentally dropped, thus requiring their lock to expire before being redelivered.

次のステップNext steps

Service Bus メッセージングの詳細については、次のトピックをご覧ください。To learn more about Service Bus messaging, see the following topics: