Azure Application Gateway を運用・トラブルシューティングする中で、「Request Timeout を伸ばせば解決するのか?」「TCP 接続の再利用(Keep-Alive)とはどう関係しているのか?」 と疑問に思ったことはありませんか?
本記事では、一見別物に見える Request Timeout と TCP 接続再利用 の仕組みを整理し、タイムアウト発生がシステムのパフォーマンスやバックエンド負荷に与える隠れた影響について分かりやすく解説します。
1. 基礎知識:それぞれの役割
まず前提として、この2つは 「管理している対象の寿命」 が全く異なります。
Request Timeout とは?(リクエスト寿命)
Application Gateway の Backend Settings で設定する Request Timeout は、「バックエンドサーバーからのレスポンスを待つ上限時間」 です。
-
正常系(Timeout = 30秒 / 処理 = 20秒):
Client➔App Gateway➔Backend (20s)➔ 正常応答 (200 OK) -
異常系(Timeout = 10秒 / 処理 = 20秒):
Client➔App Gateway➔Backend (10s経過)➔ 504 Gateway Timeout
TCP 接続再利用(Connection Reuse)とは?(接続寿命)
TCP 通信では、接続を確立するために 3-way Handshake(SYN ➔ SYN-ACK ➔ ACK) が必要です。リクエスト毎に接続を確立・切断していると、ハンドシェイクのオーバーヘッドで効率が低下します。
【再利用なし(非効率)】
Req 1 ➔ TCPハンドシェイク ➔ 処理 ➔ 切断
Req 2 ➔ TCPハンドシェイク ➔ 処理 ➔ 切断
【TCP 接続再利用(高効率)】
TCP Connection #1 確立
├─ Req 1 ➔ Res 1
├─ Req 2 ➔ Res 2
└─ Req 3 ➔ Res 3
Application Gateway はバックエンドとの TCP 接続を維持(Keep-Alive)し、同じ TCP 接続上で複数のリクエストを順番に処理 することで通信効率を高めています。
2. 「リクエスト寿命」と「接続寿命」は別物
ここが最も重要なポイントです。
| 項目 | Request Timeout | TCP 接続再利用 |
|---|---|---|
| 管理対象 | 1つのリクエストの寿命 | TCP コネクション全体の寿命 |
| 制御内容 | レスポンスを何秒待つか | 接続をどれだけ維持・使い回すか |
| 設定場所 | Backend Settings | プロトコル仕様 / Keep-Alive 設定 |
「Request Timeout = 30秒」に設定していても、30秒後に TCP 接続が切れるわけではありません。両者は独立した概念として動作しています。
3. なぜ「別物」なのに影響し合うのか?
概念としては独立していますが、タイムアウト(504)が頻発すると TCP 接続再利用の効率が著しく低下 します。
正常時の挙動(効率的)
バックエンドが高速に応答している場合、1本の TCP 接続が長く維持され、次々とリクエストが再利用されます。
[ TCP Stream #1 ]
Client/AppGW ── Request A ──> Backend
Client/AppGW <── Response A ─ Backend
Client/AppGW ── Request B ──> Backend
Client/AppGW <── Response B ─ Backend
(TCP接続を維持し続けるため CPU負荷減・応答性向上)
Timeout 発生時の挙動(連鎖的な悪影響)
リクエストがタイムアウトすると、プロキシやロードバランサーは「異常状態が発生した可能性のある接続」と判断し、その TCP 接続を安全のために切断(または再利用プールから除外)します。
[ TCP Stream #1 ]
AppGW ── Request A ──> Backend (処理遅延)
AppGW ── (Timeout 発生 / 504をクライアントへ返却)
AppGW ── [ RST または FIN で TCP 接続を切断 ]
[ TCP Stream #2 ] ※次のリクエストは新規に接続を作り直す必要が発生
AppGW ── 3-way Handshake ──> Backend
AppGW ── Request B ─────────> Backend
この結果、以下の悪循環(負のスパイラル)が発生します。
タイムアウト発生
│
▼
TCP 接続の強制破棄・除外
│
▼
新規 TCP ハンドシェイクの急増
│
▼
バックエンドサーバーの CPU / ネットワーク負荷増大
│
▼
さらに応答が遅れ、新たなタイムアウトを誘発
HTTP/2 環境では影響がさらに極大化する
HTTP/1.1 では「1接続 = 1リクエストの順次処理」ですが、HTTP/2 は 1 つの TCP 接続上に複数のストリーム(リクエスト)を多重化 します。
1本の TCP 接続の価値が非常に高いため、タイムアウトによって TCP 接続がリセットされると、相乗りしていた他の通信や後続処理への影響(パフォーマンス低下)が HTTP/1.1 以上に大きく なります。
4. パケットキャプチャで見える違い
バックエンド側で Wireshark や tcpdump などのパケットキャプチャを取得すると、この挙動の違いが顕著に現れます。
-
正常時(接続再利用が機能している):
同一の TCP Stream ID(例:#15)の中で、Request A ➔ Response A、Request B ➔ Response Bが連続して観測される。 -
Timeout 頻発時:
Request Aの後に応答がなくタイムアウトし、次のRequest Bは新しい TCP Stream ID(例:#16)、Request Cは#17のように、短い寿命の TCP セッションが大量生成 される。
5. トラブルシューティングのまとめ
504 Gateway Timeout が発生した際、「とりあえず Request Timeout の設定値を伸ばす」という対処をしてしまいがちですが、根本原因の確認が不可欠です。
💡 トラブル発生時のチェックリスト
- バックエンドの処理時間: アプリケーションログで処理遅延の原因(DBクエリ遅延、外部API待ち等)がないか?
- 新規 TCP 接続数の推移: メトリクスで新規 TCP 接続数が急増していないか?
- TCP セッション状態: バックエンド側で SYN 待ちや
TIME_WAIT/CLOSE_WAITが滞留していないか?- 接続再利用率: パケットキャプチャで同一 Stream 上の通信が継続しているか?
結論
- Request Timeout は「リクエストの寿命」、TCP 接続再利用 は「接続の寿命」。
- タイムアウトが頻発すると 接続の使い回しがきかなくなり、新規 TCP 接続のコストでバックエンドに二次災害的な負荷がかかる。
- 504 エラー対策は、タイムアウト値の変更だけでなく、バックエンドの応答性能と TCP 接続状況をセットで確認する ことが極めて重要です。