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は「張る」より「維持する」設計が基本です。
あわせて読みたい


TIME_WAITが大量発生する原因と対策
Linuxサーバーでネットワーク遅延や接続エラーが増えた際、 ss や netstat を確認すると TIME_WAIT が大量に残っているケースがあります。 TIME_WAIT自体は異常ではあり…
あわせて読みたい


エフェメラルポート枯渇の見抜き方と対処法【TIME_WAITとの関係を理解する】
Linuxサーバーで「突然外部通信ができなくなった」「再起動すると一時的に直る」 といった障害の原因として、見落とされがちなのが エフェメラルポート枯渇です。 本記…
あわせて読みたい


CLOSE_WAITが増え続ける原因とアプリ側の修正ポイント【Linux実務解説】
Linuxサーバーで CLOSE_WAIT が増え続けて減らない 状態は、 ネットワーク障害に見えて、実際にはほぼ100%アプリケーションの問題です。 本記事では、CLOSE_WAITが発生…
