サーバーが悲鳴を上げる「TIME_WAITの正体」と、賢い付き合い方
こんにちは。ネットワーク運用を20年以上やってきた現場の人間として、今日は皆さんが必ず一度は頭を抱える「TIME_WAIT問題」についてお話しします。
Webサーバーを運用していると、アクセスが急増したタイミングで突然サイトが重くなったり、接続エラーが多発したりすることがありますよね。そんな時、サーバーにログインして ss コマンドを叩くと、画面を埋め尽くすほどの TIME_WAIT の文字。
「サーバーが壊れたのか?」と焦る必要はありません。実はこれ、サーバーが「終わった通信の残骸」を律儀に片付けている最中の姿なんです。今日は、この「残骸」とどう賢く付き合っていくか、紐解いていきましょう。
—
1. TIME_WAITは「配達完了のサイン」を待っている状態
TIME_WAIT を理解するために、郵便配達を想像してみてください。
あなたが手紙(データ)を送り、相手から「届いたよ!」という返事が来た。これで用事は済みましたよね。でも、ネットワークの世界では、「本当に相手に『届いたよ』というメッセージが正しく伝わったか?」を念のために確認する時間が必要なんです。
もし、すぐに接続を完全に破棄してしまうと、遅れて届いた古いデータが新しい通信に混ざり込んでしまう事故が起きるかもしれません。だからサーバーは、接続を閉じた後も「もし何か言い残したことがあれば、あと少しだけ待ってるよ」と、一定期間(だいたい60秒〜2分ほど)その席を予約したまま待機します。これが TIME_WAIT です。
問題は、この「待機席」の数には限りがあるということです。大量の短い通信(短命接続)が次々と発生すると、待機席がすべて埋まってしまい、新しい接続を受け入れられなくなってしまうのです。
—
2. まずは現状を確認しよう:ss コマンドの出番
まずは、自分のサーバーで今どれくらいの接続が待機状態にあるのか見てみましょう。昔は netstat が主流でしたが、今はより高速で詳細な ss コマンドを使うのがエンジニアの流儀です。
# 現在のTIME_WAIT状態の接続数をカウントするコマンド
ss -tan | grep TIME-WAIT | wc -l
もしこの数字が数百、数千と跳ね上がっているなら、それはサーバーが「お片付け」に追われてパンク寸前だというサインです。
—
3. 「使い回し」の知恵:tcp_tw_reuse で解決する
待機席が足りないなら、「古い席を有効活用すればいいじゃないか」というのが、OSが用意してくれている解決策です。それが net.ipv4.tcp_tw_reuse という設定です。
これは、「まだ待機中だけど、この接続はもう安全そうだから、次の通信で再利用しちゃおう!」という、非常に賢い機能です。これを有効にすることで、TIME_WAIT に悩まされることは劇的に減ります。
設定の手順
1. 設定ファイルを開きます。
sudo vi /etc/sysctl.conf
2. ファイルの末尾に以下の行を追記します。
# TIME_WAIT状態のソケットを再利用可能にする
net.ipv4.tcp_tw_reuse = 1
3. 設定をすぐに反映させます。
sudo sysctl -p
たったこれだけで、サーバーの負荷状況は驚くほど改善されるはずです。
—
4. 運用上の注意点:魔法の杖ではない
ただし、現場のエンジニアとして一つだけ釘を刺させてください。「設定すれば全部解決!」という甘い話ばかりではありません。
tcp_tw_reuseはあくまで「クライアント側」の通信に効く: Webサーバーが別のデータベースやAPIサーバーに接続する際の「クライアントとしての通信」には非常に有効です。- 根本原因はアプリにあるかも: もし
TIME_WAITが異常に多い場合、アプリケーション側で「接続のたびにオープンとクローズを繰り返している(コネクションプーリングをしていない)」可能性を疑ってください。通信を毎回切るのではなく、繋ぎっぱなしにして使い回す工夫(Keep-Aliveなど)こそが、最もエレガントな解決策です。
—
最後に:まずは一歩ずつ
インフラの世界では、コマンド一つでサーバーの挙動がガラリと変わる瞬間があります。怖いと感じるかもしれませんが、それは皆さんが「サーバーの指揮者」になった証拠です。
まずは ss コマンドで今の様子を覗いてみて、設定を一つ変えてみる。そんな小さな試行錯誤の積み重ねが、いつかあなたを「どんなトラブルも怖くない」エンジニアへと成長させてくれるはずです。
現場からは以上です!また次のトラブルでお会いしましょう(笑)。
コメント