Service Bus の配信不能キューの概要

Azure Service Bus キューおよびトピック サブスクリプションでは、配信不能キュー (DLQ) と呼ばれるセカンダリ サブキューが提供されます。 配信不能キューを明示的に作成する必要はなく、削除したり、メイン エンティティとは別に管理したりすることはできません。

この記事では、Service Bus の配信不能キューについて説明します。 説明の多くは、GitHub の配信不能キューのサンプルに示されています。

配信不能キュー

配信不能キューの目的は、受信者に配信できないメッセージ、または処理できなかったメッセージを保持することです。 したがって、メッセージを DLQ から取り出して、検査することができます。 アプリケーションは演算子を利用して、問題を修正してメッセージを再送信し、エラーが発生していたという事実をログに記録してから修正処置を行います。

API とプロトコルの観点では、DLQ は他のキューとほとんど同じですが、メッセージを再送信できるのは親エンティティの配信不能操作でのみである点が異なります。 また、有効期間は監視されず、DLQ のメッセージを配信不能にすることはできません。 配信不能キューでは、ピーク ロック配信やトランザクション操作が完全にサポートされます。

DLQ は自動的にクリーンアップされません。 DLQ から明示的に取得し、配信不能メッセージを完了するまで、メッセージは DLQ に残ります。

DLQ のメッセージ数

配信不能キュー内のメッセージの数をトピック レベルで取得することはできません。 これは、メッセージがトピック レベルに存在しないためです。 送信者がトピックにメッセージを送信すると、メッセージはミリ秒以内にトピックのサブスクリプションに転送されるため、トピック レベルには存在しなくなります。 したがって、トピックのサブスクリプションに関連付けられている DLQ にメッセージが表示されます。 次の例では、Service Bus Explorer で、サブスクリプション "test1" の DLQ に現在 62 件のメッセージがあることが示されています。

Image showing 62 messages in the dead-letter queue.

Azure CLI コマンド az servicebus topic subscription show を使用して、DLQ のメッセージ数を取得することもできます。

DLQ にメッセージを移動する

Service Bus には、メッセージがメッセージング エンジン自体から DLQ にプッシュされる原因となるアクティビティがいくつかあります。 アプリケーションは明示的にメッセージを DLQ に移動することもできます。 次の 2 つのプロパティ (配信不能の理由と説明) は、配信不能メッセージに追加されます。 アプリケーションでは配信不能理由のプロパティに対して独自のコードを定義できますが、システムでは以下の値が設定されます。

配信不能メッセージの理由 配信不能メッセージ エラーの説明
HeaderSizeExceeded このストリームのサイズ クォータを超えています。
TTLExpiredException メッセージの有効期限が切れているため、配信不能です。 詳細については、「Time to live」セクションを参照してください。
Session ID is null. (セッション ID は Null です。) セッションが有効なエンティティではセッション ID が Null のメッセージは許可されません。
MaxTransferHopCountExceeded キュー間で転送するときに許容される最大ホップ数を超えました。 この値は 4 に設定されています。
MaxDeliveryCountExceeded 最大数の配信試行後、メッセージを使用できませんでした。 詳細については、「最大配信数」セクションを参照してください。

最大配信数

Service Bus のキューとサブスクリプションに対してメッセージの配信を試行できる回数には制限があります。 既定値は 10 です。 メッセージがピーク ロック状態で配信されたが、明示的に破棄されたかロックが期限切れになった場合は、メッセージの配信回数が増えます。 配信回数が上限を超えると、メッセージは DLQ に移動されます。 DLQ のメッセージの配信不能理由は MaxDeliveryCountExceeded に設定されます。 この動作を無効にすることはできませんが、最大配信回数を大きい数に設定することはできます。

Time to Live

キューまたはサブスクリプションで配信不能を有効にすると、有効期限が切れたすべてのメッセージは DLQ に移動されます。 配信不能理由コードは TTLExpiredException に設定されます。

遅延メッセージは、有効期限が切れても、消去されたり、配信不能キューに移動されたりすることはありません。 この動作は仕様です。

サブスクリプション ルールの処理中のエラー

フィルター評価の例外で配信不能を有効にすると、サブスクリプションの SQL フィルター規則の実行中に発生したエラーは、問題のあるメッセージと共に DLQ にキャプチャされます。 このオプションは、すべてのメッセージ型がサブスクライバーを持つわけではない運用環境では使用しないでください。

アプリケーション レベルの配信不能処理

システム指定の配信不能処理機能に加え、アプリケーションでは DLQ を使用して許容できないメッセージを明示的に拒否できます。 それらには、何らかのシステムの問題により適切に処理できないメッセージ、誤った形式のペイロードを保持するメッセージ、メッセージ レベルのセキュリティ スキームの使用時に認証に失敗したメッセージなどがあります。

これを行うには、ServiceBusReceiver.DeadLetterMessageAsync メソッドを呼び出します。

DeadLetterReason に例外の型を、DeadLetterDescription に例外のスタック トレースを含めることをお勧めします。これにより、メッセージが配信不能になる問題の原因のトラブルシューティングが容易になるからです。 これにより、一部のメッセージが Standard レベルの Azure Service Bus に対する 256 KB のクォータ制限を超える可能性があることに注意してください。さらに、これは運用環境に対しては Premium レベルを使用する必要があることを示しています。

自動転送シナリオでの配信不能

メッセージは、以下の条件の下で配信不能キューに送信されます。

  • メッセージが、連結されている 5 つ以上のキューまたはトピックを通過する。
  • 送信先キューまたはトピックが無効または削除されている。
  • 送信先キューまたはトピックがエンティティの最大サイズを超えている。

経由送信シナリオでの配信不能

  • 宛先キューまたはトピックが無効になっている場合、メッセージはソース・キューの転送配信不能キュー (TDLQ) に送信されます。
  • 宛先キューまたはトピックが削除されていると、404 例外が発生します。
  • 宛先キューまたはエンティティがエンティティ サイズを超えた場合、メッセージはソース キューの TDLQ に送信されます。

配信不能キューへのパス

配信不能キューにアクセスするには、次の構文を使用します。

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

再処理する配信不能メッセージの送信

配信不能キューに入ってしまったメッセージ内には重要なビジネス データが存在する可能性があるため、メッセージが配信不能になる原因となった元々の状況にオペレーターが対処し終えたら、それらのメッセージを再処理することが望ましいです。

Azure Service Bus Explorer などのツールを使用すると、キューとトピックの間でメッセージを手動で移動できます。 配信不能キューに移動する必要があるメッセージが多数存在する場合、このようなコードで、それらを一度に移動できます。 オペレーターは多くの場合、どの種類のメッセージが処理に失敗したのか、どのソース キューからのものなのか、どのような理由によるものなのかのトラブルシューティングを行うだけでなく、再処理のためにメッセージのバッチを再送信できるように、ユーザー インターフェイスが用意されていることを望みます。 NServiceBus を使用した ServicePulse などのツールは、これらの機能を提供します。

次のステップ

メッセージの期限切れによる配信不能処理設定のさまざまな構成方法については、キューまたはサブスクリプションの配信不能処理の有効化に関する記事を参照してください。