Azure Service Bus のトラブルシューティング ガイド

この記事では、Azure Service Bus の使用時に発生するいくつかの問題に関するトラブルシューティングのヒントと推奨事項について説明します。

接続の問題

サービスへの接続時にタイムアウトする

ホスト環境とネットワークによっては、ReasonServiceTimeout であるTimeoutExceptionOperationCanceledException、または ServiceBusException の接続の問題がアプリケーションで発生する可能性があり、最も多く発生するのはクライアントがサービスへのネットワーク パスを見つけられない場合です。

トラブルシューティングを行うには:

  • クライアントの作成時に指定した接続文字列または完全修飾ドメイン名が正しいことを確認します。 接続文字列を取得する方法については、Service Bus の接続文字列の取得に関する記事をご覧ください。
  • ホスティング環境でファイアウォールとポートのアクセス許可を確認します。 Advanced Message Queuing Protocol (AMQP) ポート 5671 と 5672 が開かれていて、エンドポイントがファイアウォール経由で許可されていることを確認します。
  • ポート 443 を使って接続する Web ソケット トランスポート オプションを使ってみてください。 詳しくは、「トランスポートの構成」をご覧ください。
  • ネットワークが特定の IP アドレスをブロックしているかどうかを確認します。 詳しくは、許可する必要がある IP アドレスに関する記事をご覧ください。
  • 該当する場合は、プロキシの構成を確認します。 詳しくは、「トランスポートの構成」をご覧ください
  • ネットワーク接続のトラブルシューティングについて詳しくは、「[接続、証明書、またはタイムアウトの問題][#connectivity-certificate-or-timeout-issues]」をご覧ください。

Secure Sockets Layer (SSL) のハンドシェイク エラー

このエラーは、インターセプト プロキシが使用されている場合に発生する可能性があります。 調べるには、プロキシを無効にしてホスト環境でアプリケーションをテストすることをお勧めします。

ソケット不足エラー

アプリケーションでは、できる限り、Service Bus の種類をシングルトンとして扱い、アプリケーションの有効期間を通じて 1 つのインスタンスを作成して使うようにする必要があります。 作成される新しい ServiceBusClient ごとに、新しい AMQP 接続が作成されてソケットを使います。 ServiceBusClient の種類は、そのインスタンスから作成されるすべての種類の接続を管理します。 各 ServiceBusReceiverServiceBusSessionReceiverServiceBusSenderServiceBusProcessor は、関連付けられた Service Bus エンティティに対する独自の AMQP リンクを管理します。 ServiceBusSessionProcessor を使うと、同時に処理されるセッションの数に応じて、複数の AMQP リンクが確立されます。

クライアントはアイドル時のキャッシュに対して安全です。これにより、ネットワーク、CPU、メモリの使用が効率的に管理されて、非アクティブな期間中の影響を最小限に抑えることができます。 また、クライアントが不要になったら CloseAsync または DisposeAsync を呼び出して、ネットワーク リソースが適切にクリーンアップされるようにすることも重要です。

接続文字列へのコンポーネントの追加が機能しない

Service Bus クライアント ライブラリの最新世代では、Azure portal によって発行された形式の接続文字列のみがサポートされます。 接続文字列は、基本的な場所と共有キー情報のみを提供することを目的としています。 クライアントの動作の構成は、そのオプションを使って行われます。

以前の世代の Service Bus クライアントでは、接続文字列にキーと値のコンポーネントを追加することで、いくつかの動作を構成できました。 これらのコンポーネントは認識されなくなっており、クライアントの動作には影響しません。

代わりの "TransportType=AmqpWebSockets"

トランスポートの種類としての Web ソケットの構成については、「トランスポートの構成」をご覧ください。

代わりの "Authentication=Managed Identity"

マネージド ID での認証については、ID と共有アクセス資格情報に関する記事をご覧ください。 Azure.Identity ライブラリについて詳しくは、「認証と Azure SDK」をご覧ください。

ログと診断

Service Bus クライアント ライブラリは、.NET EventSource を使って情報を出力するため、さまざまな詳細レベルで情報をログするように完全にインストルメント化されています。 ログは操作ごとに実行され、操作の始点、完了、および発生した例外をマークするパターンに従います。 分析情報を提供する可能性のある追加情報も、関連する操作のコンテキストでログされます。

ログ記録を有効化する

Azure-Messaging-ServiceBus で始まるソースにオプトインするか、特性 AzureEventSource を持つすべてのソースにオプトインすることにより、任意の EventListener で Service Bus クライアント ログを利用できます。 Azure クライアント ライブラリからログを簡単にキャプチャするため、Service Bus で使われる Azure.Core ライブラリには AzureEventSourceListener が用意されています。

詳しくは、「Azure SDK for .NET を使用したログ記録」をご覧ください。

分散トレース

Service Bus クライアント ライブラリは、Application Insights SDK との統合を通じて分散トレースをサポートします。 また、.NET 5 で導入された .NET の ActivitySource 型により、OpenTelemetry 仕様も実験的にサポートします。 OpenTelemetry で ActivitySource のサポートを使用できるようにするには、ActivitySource のサポートに関する記事をご覧ください。

GA の DiagnosticActivity のサポートを使うには、Application Insights SDK と統合できます。 詳しくは、Azure Monitor での Application Insights に関する記事をご覧ください。

ライブラリによって、次のスパンが作成されます。

Message
ServiceBusSender.Send
ServiceBusSender.Schedule
ServiceBusSender.Cancel
ServiceBusReceiver.Receive
ServiceBusReceiver.ReceiveDeferred
ServiceBusReceiver.Peek
ServiceBusReceiver.Abandon
ServiceBusReceiver.Complete
ServiceBusReceiver.DeadLetter
ServiceBusReceiver.Defer
ServiceBusReceiver.RenewMessageLock
ServiceBusSessionReceiver.RenewSessionLock
ServiceBusSessionReceiver.GetSessionState
ServiceBusSessionReceiver.SetSessionState
ServiceBusProcessor.ProcessMessage
ServiceBusSessionProcessor.ProcessSessionMessage
ServiceBusRuleManager.CreateRule
ServiceBusRuleManager.DeleteRule
ServiceBusRuleManager.GetRules

ほとんどのスパンはわかりやすいものであり、その名前が示す操作の間に開始および停止されます。 他のものを結び付けるスパンは Message です。 メッセージは、送信およびスケジュール操作中にライブラリによって ServiceBusMessage.ApplicationProperties プロパティに設定される Diagnostic-Id を介してトレースされます。 Application Insights では、Message スパンは、メッセージとの対話に使われた他のさまざまなスパンへのリンクとして表示されます。たとえば、ServiceBusReceiver.Receive スパン、ServiceBusSender.Send スパン、ServiceBusReceiver.Complete スパンなどはすべて Message スパンからリンクされます。 Application Insights でのこの表示例を次に示します。

Image showing a sample distributed trace.

上のスクリーンショットでは、ポータルの Application Insights で見ることができるエンド ツー エンドのトランザクションが示されています。 このシナリオでは、アプリケーションはメッセージを送信し、ServiceBusSessionProcessor を使ってメッセージを処理します。 Message アクティビティは、ServiceBusSender.SendServiceBusReceiver.ReceiveServiceBusSessionProcessor.ProcessSessionMessageServiceBusReceiver.Complete にリンクされます。

送信側の問題のトラブルシューティング

複数のパーティション キーを含むバッチを送信できない

アプリでパーティション対応のエンティティにバッチを送信するときは、1 回の送信操作に含まれるすべてのメッセージが同じ PartitionKey を保持している必要があります。 エンティティがセッション対応の場合は、SessionId プロパティについて同じ要件が当てはまります。 PartitionKey または SessionId の値が異なるメッセージを送信するには、メッセージを別の ServiceBusMessageBatch インスタンスにグループ化するか、ServiceBusMessage インスタンスのセットを受け取る SendMessagesAsync のオーバーロードに対する個別の呼び出しにそれらを含めます。

バッチの送信が失敗する

メッセージのバッチは、2 つ以上のメッセージを含む ServiceBusMessageBatch、または 2 つ以上のメッセージが渡される SendMessagesAsync の呼び出しのいずれかです。 このサービスでは、メッセージのバッチが 1 MB を超えることはできません。 この動作は、Premium レベルの大きいメッセージのサポート機能が有効になっているかどうかに関係なく当てはまります。 1 MB を超えるメッセージを送信する場合は、他のメッセージとグループにするのではなく、個別に送信する必要があります。 残念ながら、ServiceBusMessageBatch の種類では、サイズがサービスによって制限され、変更される可能性があるため、現在、バッチに 1 MB を超えるメッセージが含まれていないことの検証はサポートされていません。 そのため、Premium の大きいメッセージのサポート機能を使う場合は、1 MB を超えるメッセージを個別に送信していることを確認してください。

受信側の問題のトラブルシューティング

返されるメッセージの数が、バッチ受信で要求された数と一致しない

バッチ受信操作を試みるとき、つまり ReceiveMessagesAsync メソッドに maxMessages として 2 以上の値を渡すときは、キューまたはサブスクリプションがその時点でその数のメッセージを使用でき、構成されている maxWaitTime がすべて経過していない場合でも、要求した数のメッセージを受け取る保証はありません。 スループットを最大にし、ロックの期限が切れないようにするには、受信側は、最初のメッセージをネットワーク経由で受け取った後、処理のためにメッセージをディスパッチする前に、さらに 20 ミリ秒だけ追加のメッセージを待ちます。 maxWaitTime は、受信側が "最初の" メッセージの受信を待機する時間を制御します。後続のメッセージについては 20 ミリ秒待機します。 そのため、アプリケーションでは、入手できるすべてのメッセージを 1 回の呼び出しで受け取るものと想定しないようにする必要があります。

ロックの有効期限が切れる前にメッセージまたはセッションのロックが失われる

Service Bus サービスでは、ステートフルな AMQP プロトコルが使われます。 このプロトコルの性質上、メッセージが受信されてから解決されるまでの間に、クライアントとサービスを接続するリンクがデタッチされた場合、リンクを再接続してもメッセージを解決できません。 短時間の一時的なネットワーク障害、ネットワークの停止、またはサービスによる 10 分間のアイドル タイムアウトの適用が原因で、リンクがデタッチされる可能性があります。 リンクの再接続は、リンクを必要とする操作 (つまり、メッセージの解決または受信) の一部として自動的に行われます。 このような状況では、ロックの有効期限がまだ経過していない場合でも、ReasonMessageLockLost または SessionLockLost が設定された ServiceBusException を受け取ります。

スケジュールされたメッセージまたは遅延メッセージを参照する方法

スケジュールされたメッセージと遅延メッセージは、メッセージをクイック表示するときに含まれます。 これらは、ServiceBusReceivedMessage.State プロパティによって識別できます。 遅延メッセージの SequenceNumber を取得したら、ReceiveDeferredMessagesAsync メソッドを使ってロック付きでそれを受信できます。

トピックを操作するときは、スケジュールされたエンキュー時間までメッセージはトピックに残るので、サブスクリプションのスケジュールされたメッセージをクイック表示することはできません。 回避策として、ServiceBusReceiver を作成してトピック名を渡すことで、このようなメッセージをクイック表示できます。 トピック名を使っているときは、受信側で他の操作が機能しません。

すべてのセッションのセッション メッセージを参照する方法

通常の ServiceBusReceiver を使って、すべてのセッションをクイック表示できます。 ServiceBusSessionReceiver を使うと特定のセッションをクイック表示できますが、セッション ロックを取得する必要があります。

メッセージ本文にアクセスするときにスローされる NotSupportedException

この問題が最もよく発生するのは、異なる AMQP メッセージ本文形式を使用する別のライブラリから送信されたメッセージを受信したときです。 この種のメッセージを操作している場合は、AMQP メッセージ本文のサンプルを参照して、メッセージ本文にアクセスする方法を確認してください。

プロセッサの問題のトラブルシューティング

自動ロックの更新が機能しない

自動ロックの更新では、システム時刻に基づいて、メッセージまたはセッションのロックを更新するタイミングが決定されます。 システム時刻が正確でない場合 (たとえば、クロックが遅い場合)、ロックが失われる前にロックの更新が行われない可能性があります。 自動ロックの更新が機能しない場合は、システム時刻が正確であることを確認してください。

高いコンカレンシーを使うと、プロセッサがハングしたか、待ち時間の問題が発生したように見える

この動作は、多くの場合、スレッド不足が原因で発生します。具体的には、セッション プロセッサを使っていて、maxConcurrentSessions に対してマシン上のコア数と比べて非常に高い値を使用した場合です。 最初に調べるのは、どのイベント ハンドラーでも非同期での同期を行っていないことを確認することです。 非同期での同期を行うと、デッドロックとスレッド不足が簡単に発生します。 非同期での同期を行っていない場合でも、ハンドラー内の純粋な同期コードがスレッド不足の原因になる可能性があります。 たとえば、純粋な非同期コードがあるため、問題ではないと判断した場合は、[TryTimeout][TryTimeout] を増やしてみてください。 これにより、特にセッション プロセッサを使うときに発生するコンテキスト切り替えとタイムアウトの数が減ることで、スレッド プールの負荷が軽減されます。 [TryTimeout][TryTimeout] の既定値は 60 秒ですが、最大 1 時間まで設定できます。 手始めに TryTimeout を 5 分に設定し、そこから繰り返してテストすることをお勧めします。 これらのどの方法でも解決しない場合は、単純に複数のホストにスケールアウトする必要があります。それにより、アプリケーションでのコンカレンシーを減らす一方で、複数のホストでアプリケーションを実行して目的の全体的なコンカレンシーを実現します。

参考情報:

セッション プロセッサによるセッションの切り替えに時間がかかりすぎる

これは、[SessionIdleTimeout][SessionIdleTimeout] を使って構成できます。これは、諦めて次のものに移る前にセッションからのメッセージの受信を待機する時間をプロセッサに指示します。 これは、各セッションに少数のメッセージしかない、使用量の少ないセッションが多数ある場合に便利です。 各セッションに多くのメッセージが含まれると予想される場合に、この設定を小さくし過ぎると、必要がないのにセッションが終了するようになるため、生産性が低下する可能性があります。

プロセッサがすぐに停止する

これは、多くの場合、デモまたはテストのシナリオで見られます。 StartProcessingAsync は、プロセッサが起動した直後に戻ります。 このメソッドを呼び出しても、プロセッサの実行中にアプリケーションがブロックされて維持されることはないため、これを行うには他のメカニズムが必要になります。 デモやテストの場合は、プロセッサを起動した後に Console.ReadKey() の呼び出しを追加するだけで十分です。 運用シナリオでは、[BackgroundService][BackgroundService] のような何らかのフレームワーク統合を使って、プロセッサの起動と破棄に使用できる便利なアプリケーション ライフサイクル フックを提供することが必要になる場合があります。

トランザクションのトラブルシューティング

Service Bus でのトランザクションに関する一般的な情報については、「[Service Bus のトランザクション処理の概要][Transactions]」をご覧ください。

サポート対象の操作

トランザクションの使用時には、すべての操作がサポートされるわけではありません。 サポートされているトランザクションの一覧については、「[トランザクション スコープ内での操作][TransactionOperations]」をご覧ください。

タイムアウト

トランザクションは[一定の期間][TransactionTimeout]の後でタイムアウトするため、トランザクション スコープ内で発生する処理はこのタイムアウトに従うことが重要です。

トランザクション内の操作が再試行されない

これは仕様です。 次のようなシナリオについて考えます。トランザクション内でメッセージを完了しようとしていますが、一時的なエラーが発生します (ReasonServiceCommunicationProblem に設定された ServiceBusException など)。 要求はサービスに対して実際に行われているとします。 クライアントが再試行した場合、サービスは 2 つの完了要求を受け取ります。 最初の完了は、トランザクションがコミットされるまで終わりません。 2 番目の完了は、最初の完了が終わる前には評価さえできません。 クライアント上のトランザクションは、完了が終わるのを待っています。 これにより、サービスはクライアントがトランザクションを完了するのを待っているのに、クライアントはサービスが 2 番目の完了操作を確認するのを待っているため、デッドロックが発生します。 トランザクションは最終的に 2 分後にタイムアウトしますが、これは不適切なユーザー エクスペリエンスです。 このため、トランザクション内では操作は再試行されません。

エンティティをまたぐトランザクションが機能していない

複数のエンティティを含むトランザクションを実行するには、ServiceBusClientOptions.EnableCrossEntityTransactions プロパティを true に設定する必要があります。 詳しくは、[エンティティをまたぐトランザクション][CrossEntityTransactions]のサンプルをご覧ください。

クォータ

Service Bus のクォータについては、[こちら][ServiceBusQuotas]をご覧ください。

接続、証明書、またはタイムアウトの問題

次の手順は、*.servicebus.windows.net のすべてのサービスの接続、証明書、タイムアウトの問題のトラブルシューティングに役立ちます。

  • https://<yournamespace>.servicebus.windows.net/ をブラウザまたは wget で参照します。 これは、IP フィルタリング、仮想ネットワーク、または証明書チェーンの問題 (Java SDK の使用時には一般的) があるかどうかを確認するのに役立ちます。

    成功したメッセージの例を次に示します。

    <feed xmlns="http://www.w3.org/2005/Atom"><title type="text">Publicly Listed Services</title><subtitle type="text">This is the list of publicly-listed services currently available.</subtitle><id>uuid:27fcd1e2-3a99-44b1-8f1e-3e92b52f0171;id=30</id><updated>2019-12-27T13:11:47Z</updated><generator>Service Bus 1.1</generator></feed>
    

    失敗したエラー メッセージの例を次に示します。

    <Error>
        <Code>400</Code>
        <Detail>
            Bad Request. To know more visit https://aka.ms/sbResourceMgrExceptions. . TrackingId:b786d4d1-cbaf-47a8-a3d1-be689cda2a98_G22, SystemTracker:NoSystemTracker, Timestamp:2019-12-27T13:12:40
        </Detail>
    </Error>
    
  • 次のコマンドを実行して、ファイアウォールでポートがブロックされているかどうかを確認します。 使用されるポートは、443 (HTTPS)、5671 と 5672 (AMQP)、9354 (Net Messaging/SBMP) です。 使用するライブラリによっては、他のポートも使用されます。 5671 ポートがブロックされているかどうかを確認するサンプル コマンドを次に示します。 C

    tnc <yournamespacename>.servicebus.windows.net -port 5671
    

    Linux の場合:

    telnet <yournamespacename>.servicebus.windows.net 5671
    
  • 接続の問題が断続的に発生する場合は、次のコマンドを実行して、破棄されたパケットがあるかどうかを確認します。 このコマンドは、1 秒ごとに 25 件の異なる TCP 接続をサービスと確立しようとします。 次に、成功または失敗した数を確認し、TCP 接続の待機時間も確認します。 psping ツールは、pspingからダウンロードできます。

    .\psping.exe -n 25 -i 1 -q <yournamespace>.servicebus.windows.net:5671 -nobanner     
    

    tncping などの他のツールを使用している場合は、同等のコマンドを使用できます。

  • 前の手順で解決できない場合は、ネットワーク トレースを取得して Wireshark などのツールを使用して分析します。 必要に応じて Microsoft サポート にお問い合わせください。

  • 接続の許可リストに追加する適切な IP アドレスを見つけるには、「どのような IP アドレスを許可リストに追加する必要がありますか」を参照してください。

2026 年 9 月 30 日に Azure Service Bus 用の SBMP プロトコルのサポートを終了するため、2026 年 9 月 30 日以降、このプロトコルを使用できなくなります。 その日付より前に、(重要なセキュリティ更新プログラムと強化された機能が提供される) AMQP プロトコルを使った最新の Azure Service Bus SDK ライブラリに移行してください。

詳細については、サポート廃止のお知らせに関するページを参照してください。

サービスのアップグレードまたは再起動で発生する可能性のある問題

現象

  • 要求が一時的に抑えられる場合があります。
  • 受信したメッセージや要求が破棄される可能性があります。
  • ログ ファイルにエラー メッセージが含まれる可能性があります。
  • アプリケーションが数秒間サービスから切断される可能性があります。

原因

バックエンド サービスのアップグレードと再起動により、アプリケーションで次のような問題が発生する可能性があります。

解決方法

アプリケーション コードで SDK を利用している場合、再試行ポリシーは既に組み込まれており、アクティブになっています。 アプリケーションやワークフローに大きな影響を与えずに、アプリケーションは再接続されます。

未承認のアクセス: 要求の送信が必要

現象

このエラーは、オンプレミスのコンピューターで、送信アクセス許可を持つユーザー割り当てマネージド ID を使って、Visual Studio から Service Bus のトピックにアクセスしようとしたときに発生する可能性があります。

Service Bus Error: Unauthorized access. 'Send' claim\(s\) are required to perform this operation.

原因

この ID には、Service Bus トピックにアクセスするためのアクセス許可がありません。

解像度

このエラーを解決するには、Microsoft.Azure.Services.AppAuthentication ライブラリをインストールします。 詳しくは、「ローカル開発用における認証」をご覧ください。

ロールにアクセス許可を割り当てる方法については、「Azure Service Bus リソースにアクセスするために Microsoft Entra ID を使用してマネージド ID を認証する」をご覧ください。

Service Bus の例外:Put トークンが失敗しました

現象

次のエラー メッセージが表示されます。

Microsoft.Azure.ServiceBus.ServiceBusException: Put token failed. status-code: 403, status-description: The maximum number of '1000' tokens per connection has been reached.

2026 年 9 月 30 日に、Azure SDK ガイドラインに準拠していない Azure Service Bus SDK ライブラリ WindowsAzure.ServiceBus、Microsoft.Azure.ServiceBus、および com.microsoft.azure.servicebus は廃止されます。 SBMP プロトコルのサポートも終了するため、2026 年 9 月 30 日以降はこのプロトコルを使用できなくなります。 この日付より前に、重要なセキュリティ更新プログラムと強化された機能が提供される、最新の Azure SDK ライブラリに移行してください。

古いライブラリは 2026 年 9 月 30 日以降も引き続き使用できますが、Microsoft から公式のサポートと更新プログラムは提供されなくなります。 詳細については、サポート廃止のお知らせに関するページを参照してください。

原因

Service Bus 名前空間への 1 つの接続で、同時リンクの認証トークンの数が制限を超えました: 1000。

解決方法

次のいずれかの手順を実行します。

  • 1 つの接続での同時リンクの数を減らすか、新しい接続を使用します
  • Azure Service Bus の SDK を使用すると、このような状況に陥ることを確実に回避できます (推奨)

データ プレーン SDK を使用している場合、リソース ロックが機能しない

現象

Service Bus 名前空間に対して削除ロックを構成しましたが、Service Bus Explorer を使用すれば名前空間内のリソース (キュー、トピックなど) を削除できます。

原因

リソース ロックは Azure Resource Manager (コントロール プレーン) で保持され、データ プレーン SDK 呼び出しによって名前空間から直接リソースが削除されるのを防ぐわけではありません。 スタンドアロンの Service Bus Explorer ではデータ プレーン SDK が使用されるため、削除が実行されます。

解像度

リソース ロックによってリソースが誤って削除されないように、Azure portal、PowerShell、CLI、または Resource Manager テンプレートを介して Azure Resource Manager ベースの API を使用してエンティティを削除することをお勧めします。

エンティティが使用できなくなった

現象

エンティティが使用できなくなったことを示すエラーが表示されます。

原因

リソースが削除されている可能性があります。 次の手順を実施して、エンティティが削除された理由を特定します。

  • アクティビティ ログをチェックして、削除に関する Azure Resource Manager 要求があるかどうかを確認します。
  • 操作ログをチェックして、削除に対する直接 API 呼び出しがあったかどうかを確認します。 操作ログを収集する方法については、「収集とルーティング」を参照してください。 スキーマと操作ログの例については、「操作ログ」を参照してください
  • 操作ログをチェックして、autodeleteonidle に関連する削除があったかどうかを確認します。

次のステップ

次の記事をご覧ください。

  • Azure Resource Manager の例外」。 この記事では、Azure Resource Manager を使用して (テンプレートまたは直接呼び出しにより) Azure Service Bus とやり取りするときに生成される例外を示します。
  • メッセージングの例外」。 この記事では、Azure Service Bus の .NET Framework によって生成される例外の一覧を示します。