Azure App Service での断続的な送信接続エラーのトラブルシューティング
この記事は、Azure App Service での断続的な接続エラーと、それに関連したパフォーマンスの問題のトラブルシューティングに役立ちます。 ソース ネットワーク アドレス変換 (SNAT) ポートの枯渇に関する詳細およびトラブルシューティング方法について説明します。 この記事の内容について不明な点がありましたら、MSDN の Azure フォーラムと Stack Overflow フォーラムで Azure エキスパートにお問い合わせください。 または、Azure サポート インシデントを送信してください。 Azure サポートのサイトに移動して、 [サポートの要求] をクリックしてください。
現象
Azure アプリ サービスでホストされているアプリケーションおよび関数で、次の 1 つ以上の現象が発生する可能性があります。
- サービス プランの全部または一部のインスタンスで応答時間が遅くなる。
- 断続的な 5xx または Bad Gateway エラー
- タイムアウト エラー メッセージ
- 外部エンドポイント (SQLDB、Service Fabric、その他のアプリ サービスなど) に接続できなかった
原因
接続が途切れる問題の主な原因は、新しい送信接続を作成している間に制限に達していることです。 以下のような制限に、到達している可能性があります。
- TCP 接続: 作成できる送信接続の数には制限があります。 送信接続の制限は、使用されるワーカーのサイズに関連付けられています。
- SNAT ポート: Azure の送信接続に関する記事では、SNAT ポートの制限と、送信接続への影響について説明します。 Azure では、送信元ネットワーク アドレス変換 (SNAT) とロード バランサー (顧客に公開されません) を使用して、パブリック IP アドレスと通信します。 Azure アプリ サービスの各インスタンスには、最初は 128 個の SNAT ポートが事前に割り当てられています。 この SNAT ポートの制限は、同じアドレスとポートの組み合わせへの接続を開くことに影響します。 アドレスとポートのさまざまな組み合わせへの接続をアプリが作成する場合、SNAT ポートを使い果たすことはありません。 SNAT ポートが使い果たされるのは、同じアドレスとポートの組み合わせへの呼び出しを繰り返したときです。 解放されたポートは必要に応じて再利用できます。 Azure ネットワーク ロード バランサーは、4 分間待機した後でないと、閉じられた接続の SNAT ポートを回収しません。
アプリケーションまたは関数で新しい接続を開くペースが速いと、128 ポートの事前割り当てクォータがすぐに枯渇する可能性があります。 その場合、さらに SNAT ポートを動的に割り当てるか、回収した SNAT ポートを再利用することで新しい SNAT ポートが利用可能になるまで、アプリケーションまたは関数はブロックされます。 アプリで SNAT ポートが不足している場合は、送信接続が途切れる問題が発生します。
問題の回避
SNAT ポートの制限を回避するための解決策は、いくつかあります。 具体的な内容を次に示します。
- 接続プール: 接続をプールすることで、同じアドレスとポートへの呼び出しに対して、新しいネットワーク接続を開かないようにすることができます。
- サービス エンドポイント: サービス エンドポイントで保護されているサービスには SNAT ポートの制限がありません。
- プライベート エンドポイント: プライベート エンドポイントで保護されているサービスには SNAT ポートの制限がありません。
- NAT ゲートウェイ: NAT ゲートウェイでは、これを介してトラフィックを送信するリソースが使用できる SNAT 送信ポートが 64,000 個あります。
SNAT ポートの問題を回避するには、同じホストとポートへの新しい接続が繰り返し作成されないようにします。 接続プールは、この問題を解決するための理解しやすい方法の 1 つです。
サービス エンドポイントがサポートされる Azure サービスが宛先であれば、リージョンの VNet 統合とサービス エンドポイントまたはプライベート エンドポイントを利用し、SNAT ポート不足問題を回避できます。 リージョンの VNet 統合を使用し、統合サブネットにサービス エンドポイントを配置すると、それらのサービスへのアプリの送信トラフィックには送信 SNAT ポート制限は適用されません。 同様に、リージョンの VNet 統合とプライベート エンドポイントを使用している場合、その宛先への送信 SNAT ポートの問題は発生しません。
送信先が Azure 外部の外部エンドポイントである場合、NAT ゲートウェイを使用すると、64,000 個の送信 SNAT ポートが提供されます。 また、他のユーザーと共有しない専用の送信アドレスが提供されます。
可能な場合は、接続プールを使用するようにコードを改良し、すべての状況を改善します。 必ずしも、この状況を軽減するのに十分な時間をかけてコードを変更できるとは限りません。 時間内にコードを変更できない場合は、他の解決策を利用してください。 問題を解決する最善策として、すべての解決策を可能な限り組み合わせることをお勧めします。 Azure サービスにはサービス エンドポイントとプライベート エンドポイントを使用し、それ以外には NAT ゲートウェイを使用してみてください。
SNAT ポートの枯渇を避けるための一般的な戦略については、Azure の送信接続に関するドキュメントの問題解決セクションで説明しています。 これらの戦略のうち、Azure アプリ サービスでホストされているアプリおよび関数に適用されるものは以下のとおりです。
接続プールを使用するようにアプリケーションを変更する
- HTTP 接続のプールについては、HttpClientFactory による HTTP 接続のプールに関するページを確認してください。
- SQL Server 接続プールの詳細については、「SQL Server の接続プール (ADO.NET)」を確認してください。
以下は、さまざまなソリューション スタックごとに接続プールを実装するためのリンクのコレクションです。
ノード
既定では、NodeJS の接続は維持されません。 実装方法の例を含め、接続プール用の一般的なデータベースとパッケージを次に示します。
HTTP キープアライブ
Java
実装方法の例を含め、JDBC 接続プールに使用される一般的なライブラリを次に示します。JDBC 接続プール。
HTTP 接続プール
PHP
PHP では接続プールがサポートされていませんが、バックエンド サーバーに対して永続的なデータベース接続を使用してみることができます。
MySQL サーバー
- 新しいバージョンの MySQLi 接続
- 以前のバージョンの PHP の mysql_pconnect
他のデータ ソース
Python
実装方法の例を含め、接続プール用の一般的なデータベースとモジュールを次に示します。
HTTP 接続プール
接続を再利用するようにアプリケーションを変更する
- Azure Functions での接続の管理に関するその他のヒントと例については、「Azure Functions での接続の管理」を参照してください。
再試行の頻度を抑えるようにアプリケーションのロジックを変更する
- 詳細なガイダンスと例については、「再試行パターン」を確認してください。
キープアライブを使用して送信アイドル タイムアウトをリセットする
- Node.js アプリのキープアライブを実装する場合は、「node アプリケーションによる発信呼び出しが多すぎる」を確認してください。
App Service 固有の詳細なガイダンス:
- ロード テストでは、現実に即したデータを、安定したフィード速度でシミュレートするようにしてください。 現実的なストレス下でアプリおよび関数をテストすることで、SNAT ポートの枯渇の問題を事前に識別し、解決することができます。
- バックエンド サービスが迅速に応答を返せることを確認します。 Azure SQL データベースのパフォーマンスの問題のトラブルシューティングについては、「Intelligent Insights を使用した Azure SQL Database のパフォーマンスに関する問題のトラブルシューティング」を参照してください。
- App Service プランをより多くのインスタンスにスケールアウトします。 スケーリングの詳細については、Azure App Service でのアプリのスケーリングに関する記事を参照してください。 App Service プランの各ワーカー インスタンスには、いくつかの SNAT ポートが割り当てられています。 より多くのインスタンスに使用量を分散させた場合、インスタンスあたりの SNAT ポート使用数が、一意のリモート エンドポイントあたり 100 件の送信接続という推奨制限値を下回る可能性があります。
- 単一の送信 IP アドレスが割り当てられ、接続数と SNAT ポート数の制限がより大きい App Service Environment (ASE) への移行を検討してください。 ASE のインスタンスごとの SNAT ポートの数は、Azure ロード バランサーの事前割り当てテーブルに基づいています。 たとえば、ASE のワーカー インスタンスの数が 1 から 50 である場合、インスタンスごとに事前割り当てされているポートは 1024 であり、ASE のワーカー インスタンスの数が 51 から 100 である場合は、インスタンスごとに事前割り当てされているポートは 512 になります。
制限はワーカーのサイズによって設定されるため、送信 TCP 制限の回避は解決しやすい問題です。 制限については、TCP 接続でのサンドボックスの VM 間数値制限に関するページで確認できます。
制限名 | 説明 | 小 (A1) | 中 (A2) | 大 (A3) | 分離層 (ASE) |
---|---|---|---|---|---|
接続 | VM 全体での接続数 | 1920 | 3968 | 8064 | 16,000 |
送信 TCP 制限を回避するために、ワーカーのサイズを大きくするか、水平方向にスケールアウトすることができます。
トラブルシューティング
2 種類の送信接続制限と、アプリの動作について把握することで、トラブルシューティングが容易になります。 アプリが同じストレージ アカウントに対して多くの呼び出しを行うことがわかっている場合、SNAT の制限を疑うことができます。 アプリがインターネット全体のエンドポイントに対して非常に多くの呼び出しを作成する場合、VM の制限に達していることが疑われます。
アプリケーションの動作の把握が不十分で原因をすぐに特定できない場合は、App Service にはその特定に役立ついくつかのツールと手法が用意されています。
SNAT ポート割り当て情報の検索
App Service 診断を使用して、SNAT ポート割り当て情報を検索したり、App Service サイトの SNAT ポート割り当てメトリックを監視したりできます。 SNAT ポート割り当て情報を検索するには、次の手順に従います。
- App Service 診断にアクセスするには、Azure portal 上の App Service Web アプリまたは App Service 環境に移動します。 左側のナビゲーションで、 [問題の診断と解決] を選択します。
- [Availability and Performance] (可用性とパフォーマンス) カテゴリを選択します。
- カテゴリの下にある使用可能なタイルの一覧から [SNAT Port Exhaustion] (SNAT ポート枯渇) タイルを選択します。 128 未満に維持することをお勧めします。 必要な場合は、引き続きサポート チケットを開くことができ、サポート エンジニアが代わりにバックエンドからメトリックを取得します。
SNAT ポート使用数はメトリックとして取得できないため、SNAT ポート使用数に基づいた自動スケールはできず、SNAT ポート割り当てメトリックに基づいて自動スケールを構成することもできません。
TCP 接続と SNAT ポート
TCP 接続と SNAT ポートは直接関連していません。 TCP 接続の使用数の検出機能は、App Service アプリの [問題の診断と解決] 管理ページに含まれています。 "TCP connections" という語句を検索して見つけます。
- SNAT ポートは外部ネットワーク フローにのみ使用されますが、TCP 接続の合計にはローカル ループバック接続が含まれます。
- プロトコル、IP アドレス、またはポートのいずれかでフローが異なる場合、異なるフローで SNAT ポートを共有できます。 TCP 接続メトリックは、すべての TCP 接続をカウントします。
- TCP 接続の制限は、ワーカー インスタンス レベルで行われます。 Azure ネットワークの送信負荷分散では、SNAT ポート制限に TCP 接続メトリックを使用しません。
- TCP 接続の制限については、TCP 接続でのサンドボックスの VM 間数値制限に関するページで説明しています。
- Azure App Service ソース ポートからの新しい送信 TCP セッションが追加されると、既存の TCP セッションは失敗します。 単一の IP を使うか、バックエンド プール メンバーを再構成して、競合を回避できます。
制限名 | 説明 | 小 (A1) | 中 (A2) | 大 (A3) | 分離層 (ASE) |
---|---|---|---|---|---|
接続 | VM 全体での接続数 | 1920 | 3968 | 8064 | 16,000 |
WebJob とデータベース接続
SNAT ポートが枯渇していて、WebJob が SQL Database に接続できない場合に、個別の Web アプリケーション プロセスによって開かれている接続の数を示すメトリックはありません。 問題のある WebJob を見つけるには、いくつかの WebJob を別の App Service プランに移動し、状況が改善するかどうか、またはいずれかのプランで問題が継続するかどうかを確認します。 問題のある WebJob が見つかるまで、このプロセスを繰り返します。