サーバーが悲鳴を上げる夜:netstatで紐解くTCP接続の「渋滞」と「ゴミ屋敷」
夜中の2時。突然の「サービスが重い」「繋がらない」というアラート。現場で何度も繰り返されるこの光景ですが、原因の多くは意外にもシンプルです。サーバーのメモリ不足やCPU高負荷ではありません。「ソケットの枯渇」、つまり、通信の「玄関」がパンクしているのです。
今日は、そんなトラブルの現場で僕たちが真っ先に叩くコマンド、netstat(あるいはその後継である ss)を使って、サーバーの中で今何が起きているのかを「郵便配達」に例えながら紐解いていきましょう。
—
TCP接続は「手紙のやり取り」と同じ
TCP接続を難しく考える必要はありません。これは、「相手に手紙を届け、返事をもらい、最後に『受け取ったよ』と報告して封筒を閉じる」という一連のやり取りです。
このとき、サーバーには「今、誰と、どんな状態の手紙をやり取りしているか」を記録する場所が必要です。これがソケット(ポート)です。しかし、この郵便受けが一杯になってしまったり、終わったはずの手紙をいつまでも机の上に放置したりすると、新しい手紙を受け取れなくなります。
これを調査するのが netstat コマンドの役割です。
—
現場で多発する「怪しいステート」を見極める
まずは、サーバーで今何が起きているかを確認するコマンドを叩いてみましょう。
# 現在のすべてのTCP接続状態を一覧表示します
# -t: TCPを表示
# -n: ホスト名やポート名を解決せず数字で表示(高速化のため必須!)
# -a: すべての接続を表示
netstat -tn
この結果に出てくる「ステート(状態)」の中で、特に注目すべき3つの「トラブルの種」を紹介します。
1. ESTABLISHED:まさに「今、通話中」
これは正常な状態です。現在、まさに通信が行われています。ここが異常に多い場合は、単にアクセスが殺到しているか、あるいは一回の通信が長すぎて「話が終わらない」状態です。
2. CLOSE_WAIT:片付けを忘れた「机の上の未処理書類」
これが現れたら要注意です。これは「相手から『切るよ』という手紙は届いたけれど、こちらのプログラムが『わかった、じゃあ封筒を閉じるね』という返事を返していない」状態です。
プログラムのコードミスで「接続を閉じる処理」が漏れていると、この状態のままソケットが溜まり続け、やがて新しい接続を受け付けなくなります。いわゆる「接続リーク」の典型です。
3. TIME_WAIT:郵便ポストに残る「終わった手紙の残骸」
通信が終わった直後、念のために数分間だけ「本当に終わったか確認する期間」として残る状態です。短時間のアクセスが大量にあると、この「残骸」が山積みになります。これが多すぎると、新しい接続を作るための「郵便番号(ポート番号)」が足りなくなります。
—
実践:問題のステートを瞬時に炙り出す
現場では、何千行ものリストを目で追うことはしません。以下のようにコマンドを組み合わせて、原因となるステートをサクッと抜き出します。
# TCP接続のステート数をカウントして、多い順に並べる魔法のコマンド
# ssコマンドはnetstatの次世代版で、動作が非常に軽快です
ss -tn | awk '{print $1}' | sort | uniq -c | sort -nr
実行結果のイメージ:
150 ESTABLISHED
80 TIME_WAIT
50 CLOSE_WAIT <-- ここが多ければ要注意!プログラムの修正が必要です
もし CLOSE_WAIT が異常に多いなら、開発チームに「プログラムがソケットを閉じ忘れていないか?」と相談に行くのが正解です。現場では、こうした数字の裏側にある「プログラムの論理」を想像することが、最短での解決に繋がります。
—
初学者の皆さんへのアドバイス
ネットワークトラブルを追うときは、「サーバーが何に困っているか」を擬人化して考えてみてください。
- 「あ、まだ返事待ちだ(
ESTABLISHED)」 - 「え、まだ片付け終わってないの?(
CLOSE_WAIT)」 - 「もう終わったのに、なんでまだ机にあるの?(
TIME_WAIT)」
このように、コマンドの結果を「郵便配達の物語」として捉えるようになると、不思議とトラブルの解決策が向こうから見えてくるようになります。
まずは自分のパソコンや検証サーバーで ss -tn を叩いてみてください。最初は数字の羅列に見えても、その一つ一つが世界中の誰かと繋がっている「手紙のやり取り」だと思うと、少しだけネットワークが身近に感じられるはずですよ。
それでは、また現場でお会いしましょう!
コメント