Service Bus の配信不能キューの概要Overview of Service Bus dead-letter queues

Azure Service Bus キューおよびトピック サブスクリプションでは、配信不能キュー (DLQ) と呼ばれるセカンダリ サブキューが提供されます。Azure Service Bus queues and topic subscriptions provide a secondary sub-queue, called a dead-letter queue (DLQ). 配信不能キューを明示的に作成する必要はなく、削除したり、メイン エンティティとは別に管理したりすることはできません。The dead-letter queue does not need to be explicitly created and cannot be deleted or otherwise managed independent of the main entity.

この記事では、Service Bus の配信不能キューについて説明します。This article describes dead-letter queues in Service Bus. 説明の多くは、GitHub の配信不能キューのサンプルに示されています。Much of the discussion is illustrated by the Dead-Letter queues sample on GitHub.

配信不能キューThe dead-letter queue

配信不能キューの目的は、受信者に配信できないメッセージ、または処理できなかったメッセージを保持することです。The purpose of the dead-letter queue is to hold messages that cannot be delivered to any receiver, or messages that could not be processed. したがって、メッセージを DLQ から取り出して、検査することができます。Messages can then be removed from the DLQ and inspected. アプリケーションは演算子を利用して、問題を修正してメッセージを再送信し、エラーが発生していたという事実をログに記録してから修正処置を行います。An application might, with help of an operator, correct issues and resubmit the message, log the fact that there was an error, and take corrective action.

API とプロトコルの観点では、DLQ は他のキューとほとんど同じですが、メッセージを再送信できるのは親エンティティの配信不能操作でのみである点が異なります。From an API and protocol perspective, the DLQ is mostly similar to any other queue, except that messages can only be submitted via the dead-letter operation of the parent entity. また、有効期間は監視されず、DLQ のメッセージを配信不能にすることはできません。In addition, time-to-live is not observed, and you can't dead-letter a message from a DLQ. 配信不能キューでは、ピーク ロック配信やトランザクション操作が完全にサポートされます。The dead-letter queue fully supports peek-lock delivery and transactional operations.

DLQ は自動的にクリーンアップされないことに注意してください。Note that there is no automatic cleanup of the DLQ. DLQ から明示的に取得し、配信不能メッセージに対して Complete() を呼び出すまで、メッセージは DLQ に残ります。Messages remain in the DLQ until you explicitly retrieve them from the DLQ and call Complete() on the dead-letter message.

DLQ にメッセージを移動するMoving messages to the DLQ

Service Bus には、メッセージがメッセージング エンジン自体から DLQ にプッシュされる原因となるアクティビティがいくつかあります。There are several activities in Service Bus that cause messages to get pushed to the DLQ from within the messaging engine itself. アプリケーションは明示的にメッセージを DLQ に移動することもできます。An application can also explicitly move messages to the DLQ.

ブローカーによってメッセージが移動され、ブローカーがメッセージに対して内部バージョンの DeadLetter メソッドを呼び出すと、DeadLetterReason および DeadLetterErrorDescription という 2 つのプロパティが追加されます。As the message gets moved by the broker, two properties are added to the message as the broker calls its internal version of the DeadLetter method on the message: DeadLetterReason and DeadLetterErrorDescription.

アプリケーションは DeadLetterReason プロパティに対して独自のコードを定義できますが、システムでは以下の値が設定されます。Applications can define their own codes for the DeadLetterReason property, but the system sets the following values.

条件Condition DeadLetterReasonDeadLetterReason DeadLetterErrorDescriptionDeadLetterErrorDescription
Always (常に)Always HeaderSizeExceededHeaderSizeExceeded このストリームのサイズ クォータを超えています。The size quota for this stream has been exceeded.
!TopicDescription.!TopicDescription.
EnableFilteringMessagesBeforePublishing and SubscriptionDescription.EnableFilteringMessagesBeforePublishing and SubscriptionDescription.
EnableDeadLetteringOnFilterEvaluationExceptionsEnableDeadLetteringOnFilterEvaluationExceptions
exception.GetType().Nameexception.GetType().Name exception.Messageexception.Message
EnableDeadLetteringOnMessageExpirationEnableDeadLetteringOnMessageExpiration TTLExpiredExceptionTTLExpiredException メッセージの有効期限が切れているため、配信不能です。The message expired and was dead lettered.
SubscriptionDescription.RequiresSessionSubscriptionDescription.RequiresSession セッション id は Null です。Session id is null. セッションが有効なエンティティではセッション ID が Null のメッセージは許可されません。Session enabled entity doesn't allow a message whose session identifier is null.
!dead letter queue!dead letter queue MaxTransferHopCountExceededMaxTransferHopCountExceeded キュー間で転送するときに許容される最大ホップ数。The maximum number of allowed hops when forwarding between queues. 値は 4 に設定されています。Value is set to 4.
Application での明示的な配信不能処理Application explicit dead lettering アプリケーションで指定Specified by application アプリケーションで指定Specified by application

MaxDeliveryCount の超過Exceeding MaxDeliveryCount

キューおよびサブスクリプションにはそれぞれ QueueDescription.MaxDeliveryCount および SubscriptionDescription.MaxDeliveryCount プロパティがあり、既定値は 10 です。Queues and subscriptions each have a QueueDescription.MaxDeliveryCount and SubscriptionDescription.MaxDeliveryCount property respectively; the default value is 10. メッセージがロック状態で配信されたが (ReceiveMode.PeekLock)、明示的に破棄されたかロックが期限切れになった場合は、メッセージの BrokeredMessage.DeliveryCount が増えます。Whenever a message has been delivered under a lock (ReceiveMode.PeekLock), but has been either explicitly abandoned or the lock has expired, the message BrokeredMessage.DeliveryCount is incremented. DeliveryCountMaxDeliveryCount を超えると、メッセージは DLQ に移動にされ、MaxDeliveryCountExceeded 理由コードが示されます。When DeliveryCount exceeds MaxDeliveryCount, the message is moved to the DLQ, specifying the MaxDeliveryCountExceeded reason code.

この動作を無効にすることはできませんが、MaxDeliveryCount を非常に大きい数に設定することはできます。This behavior cannot be disabled, but you can set MaxDeliveryCount to a very large number.

TimeToLive の超過Exceeding TimeToLive

QueueDescription.EnableDeadLetteringOnMessageExpiration または SubscriptionDescription.EnableDeadLetteringOnMessageExpiration プロパティが true に設定されている場合 (既定値は false)、期限が切れるメッセージはすべて DLQ に移動され、TTLExpiredException 理由コードが示されます。When the QueueDescription.EnableDeadLetteringOnMessageExpiration or SubscriptionDescription.EnableDeadLetteringOnMessageExpiration property is set to true (the default is false), all expiring messages are moved to the DLQ, specifying the TTLExpiredException reason code.

メイン キューまたはサブスクリプションに対してプルを実行しているアクティブな受信者が少なくとも 1 つある場合は、期限切れメッセージは単に消去され、DLQ に移動されるだけであることに注意してください (この動作は仕様によるものです)。Note that expired messages are only purged and moved to the DLQ when there is at least one active receiver pulling from the main queue or subscription; that behavior is by design.

サブスクリプション ルールの処理中のエラーErrors while processing subscription rules

SubscriptionDescription.EnableDeadLetteringOnFilterEvaluationExceptions プロパティがサブスクリプションに対して有効になっている場合、サブスクリプションの SQL フィルター ルールの実行時に発生したエラーはすべて問題のメッセージと共に DLQ にキャプチャされます。When the SubscriptionDescription.EnableDeadLetteringOnFilterEvaluationExceptions property is enabled for a subscription, any errors that occur while a subscription's SQL filter rule executes are captured in the DLQ along with the offending message.

アプリケーション レベルの配信不能処理Application-level dead-lettering

システム指定の配信不能処理機能に加え、アプリケーションでは DLQ を使用して許容できないメッセージを明示的に拒否できます。In addition to the system-provided dead-lettering features, applications can use the DLQ to explicitly reject unacceptable messages. これには、何らかのシステムの問題により適切に処理できないメッセージ、誤った形式のペイロードを保持するメッセージ、メッセージ レベルのセキュリティ スキームの使用時に認証に失敗したメッセージが含まれる可能性があります。This can include messages that cannot be properly processed due to any sort of system issue, messages that hold malformed payloads, or messages that fail authentication when some message-level security scheme is used.

ForwardTo または SendVia での配信不能シナリオDead-lettering in ForwardTo or SendVia scenarios

メッセージは、次の条件に該当するときに転送不能キューに送信されます。Messages will be sent to the transfer dead-letter queue under the following conditions:

  • メッセージが、連結されている 5 つ以上のキューまたはトピックを通過する。A message passes through more than 4 queues or topics that are chained together.
  • 送信先キューまたはトピックが無効または削除されている。The destination queue or topic is disabled or deleted.
  • 送信先キューまたはトピックがエンティティの最大サイズを超えている。The destination queue or topic exceeds the maximum entity size.

これらの配信不能メッセージを取得するために、FormatTransferDeadletterPath ユーティリティ メソッドを使用して受信者を作成することができます。To retrieve these dead-lettered messages, you can create a receiver using the FormatTransferDeadletterPath utility method.

Example

次のコード スニペットではメッセージの受信者を作成します。The following code snippet creates a message receiver. メイン キューの受信ループで、コードは Receive(TimeSpan.Zero) のメッセージを取得します。この場合、ブローカーはすぐに使用できるメッセージをすぐに返すか、結果なしで返すように求められます。In the receive loop for the main queue, the code retrieves the message with Receive(TimeSpan.Zero), which asks the broker to instantly return any message readily available, or to return with no result. コードはメッセージを受信すると、すぐに破棄し、DeliveryCount が増えます。If the code receives a message, it immediately abandons it, which increments the DeliveryCount. システムが DLQ にメッセージを移動すると、メイン キューは空になり、ループが終了し、ReceiveAsyncnull を返します。Once the system moves the message to the DLQ, the main queue is empty and the loop exits, as ReceiveAsync returns null.

var receiver = await receiverFactory.CreateMessageReceiverAsync(queueName, ReceiveMode.PeekLock);
while(true)
{
    var msg = await receiver.ReceiveAsync(TimeSpan.Zero);
    if (msg != null)
    {
        Console.WriteLine("Picked up message; DeliveryCount {0}", msg.DeliveryCount);
        await msg.AbandonAsync();
    }
    else
    {
        break;
    }
}

配信不能キューへのパスPath to the dead-letter queue

配信不能キューにアクセスするには、次の構文を使用します。You can access the dead-letter queue by using the following syntax:

<queue path>/$deadletterqueue
<topic path>/Subscriptions/<subscription path>/$deadletterqueue

.NET SDK を使用している場合、配信不能キューへのパスを取得するには、SubscriptionClient.FormatDeadLetterPath() メソッドを使用します。If you are using the .NET SDK, you can get the path to the dead-letter queue by using the SubscriptionClient.FormatDeadLetterPath() method. このメソッドは、 /$DeadLetterQueue を使用して、トピック名、サブスクリプション名、サフィックスを指定します。This method takes the topic name/subscription name and suffixes with /$DeadLetterQueue.

次の手順Next steps

Service Bus キューの詳細については、次の記事を参照してください。See the following articles for more information about Service Bus queues: