netstat を見ると大量に並ぶ TIME_WAIT。これは何者で、放置していいのか。TCPの状態遷移とあわせて解説します。
接続の開始と終了
TCPは接続の開始を3ウェイ、終了を4ウェイのやり取りで行います。
開始(3ウェイ):
SYN → / ← SYN,ACK / ACK →
終了(4ウェイ):
FIN → / ← ACK / ← FIN / ACK →
お互いが「もう送るものはない(FIN)」を伝え合って、きれいに閉じます。
主な状態
LISTEN… 待ち受け中(サーバ)ESTABLISHED… 接続確立、通信中FIN_WAIT / CLOSE_WAIT… 切断処理の途中TIME_WAIT… 自分から閉じた側が、最後に一定時間待つ状態
TIME_WAITはなぜ必要か
接続を能動的に閉じた側は、最後のACKを送ったあと、すぐには消えず一定時間(数十秒〜数分)TIME_WAIT で待ちます。理由は主に2つ。
- 最後のACKが相手に届かず、相手がFINを再送してきた時に応答できるように
- 同じIP・ポートの組が使い回されて、前の接続の遅延パケットが混ざるのを防ぐため
つまりTIME_WAITは正常な安全装置で、異常ではありません。
大量のTIME_WAITが問題になる時
短時間に大量の接続を開いて閉じるサーバ(例: バックエンドへ大量に短命接続を張るプロキシ)では、TIME_WAITがポートを埋めて、新規接続が張れなくなることがあります。
対処の考え方
- 接続を使い回す(Keep-Alive): そもそも開閉を減らすのが本筋
- コネクションプール: アプリ側で接続を再利用する
- カーネルパラメータの調整もあるが、まずはアプリの接続の張り方を見直すのが正道
調査コマンド
ss -tan state time-wait | wc -l … TIME_WAITの数
ss -tan … 状態別に一覧
まとめ
TIME_WAITは、TCPが安全に接続を閉じるための正常な状態です。数が多いこと自体は異常ではなく、問題になるのは「短命接続を大量に張る」設計の時。その場合は数をいじるより、接続を使い回す方向で解くのが本筋です。状態遷移を理解すると、netstatの見え方が変わります。