短命TCP接続が大量発生する設計ミス集【TIME_WAIT多発の根本原因】

  • URLをコピーしました!

Linuxサーバーやアプリケーションで 短命TCP接続が大量発生 すると、 TIME_WAIT増加、ポート枯渇、CPU負荷上昇など、さまざまな問題を引き起こします。

本記事では「なぜ短命TCP接続が発生するのか」をTCPの仕組みから整理し、 現場で頻出する設計ミスとその改善策を具体的に解説します。

目次

短命TCP接続とは何か

短命TCP接続とは、以下のような特徴を持つ通信です。

  • 接続してすぐ切断される
  • 1リクエスト=1コネクション
  • KeepAliveが効いていない

TCP的には以下の流れが高速で繰り返されます。

SYN → SYN/ACK → ACK → データ → FIN → FIN/ACK

これが高頻度で発生すると、OSは後処理として TIME_WAITを大量に抱えることになります。

短命TCP接続が大量発生した時の症状

  • TIME_WAITが数万〜数十万に増加
  • エフェメラルポート枯渇
  • 新規通信が張れない
  • 通信は軽いのにCPU使用率が高い
  • アプリ再起動で一時回復

まず確認すべき観測ポイント

① TCP状態の確認

ss -tan | awk '{print $1}' | sort | uniq -c

② TIME_WAITが多いか

ss -tan state time-wait | wc -l

③ 接続先ポートの特定

ss -tan state time-wait | awk '{print $5}' | sort | uniq -c | sort -nr

設計ミス① HTTP KeepAlive を使っていない

最も多い原因が KeepAlive無効 です。

  • HTTP/1.0 を使っている
  • Connection: close が指定されている
  • クライアント側で毎回接続を作り直す

結果として「1リクエスト=1TCP接続」となります。

改善策

  • HTTP/1.1 以上を使用
  • KeepAlive 有効化
  • 接続再利用設計

設計ミス② アプリが毎回 new Socket している

内部通信や外部API呼び出しで、

  • 都度ソケット生成
  • 即 close()

を繰り返すと短命接続が爆発します。

改善策

  • 接続プールの利用
  • コネクション再利用

設計ミス③ DB接続を毎回張り直している

DB接続もTCPです。

以下のような実装は要注意です。

  • リクエストごとにDB接続
  • プール未使用

短命TCP接続+DB負荷のダブルパンチになります。

改善策

  • DBコネクションプール導入
  • 最大接続数制御

設計ミス④ 負荷分散配下でKeepAliveが切れる

ロードバランサ配下では以下が起きがちです。

  • LB側でKeepAlive無効
  • LBのidle timeoutが短い

結果として、クライアントは再接続を強いられます。

改善策

  • LBのidle timeout見直し
  • アプリ側KeepAliveと整合

設計ミス⑤ タイムアウトが短すぎる

過度に短いタイムアウトは、

  • 途中切断
  • 再接続ループ

を引き起こし、短命接続を量産します。

改善策

  • 現実的な timeout 値設定
  • 通信特性に合わせた調整

OSチューニングで誤魔化せるか?

以下の設定は一時的な緩和にしかなりません。

  • tcp_tw_reuse
  • tcp_fin_timeout

設計ミスを放置したままでは必ず再発します。

設計見直し時のチェックリスト

  • 接続は再利用できているか
  • KeepAliveが正しく有効か
  • プールが導入されているか
  • LBとのタイムアウト整合
  • 異常系でcloseされるか

まとめ

短命TCP接続の大量発生は、ほぼ確実に 設計の問題 です。

OS設定で耐えようとする前に、 「接続を使い捨てていないか?」 を疑ってください。

TCPは「張る」より「維持する」設計が基本です。

目次