CPUもメモリも余裕があるのに、Nginxが突如として「502 Bad Gateway」や接続タイムアウトを頻発させる。この不可解な障害の背後には、大抵の場合「TIME_WAITソケットの枯渇」とカーネルパラメータの設定不足が潜んでいる。本稿では、LinuxカーネルレベルでTCPスタックを最適化し、Nginxの限界性能を引き出す手法を解説する。
TIME_WAIT枯渇とは、TCPコネクション切断後の待機状態(TIME_WAIT)のソケットがシステム上限に達し、新規接続が拒否される現象である。 sysctl.confにてtcp_tw_reuseを有効化し、somaxconnで接続キューを拡張することで、このボトルネックを劇的に解消できる。
アナロジーで理解するTIME_WAITと接続キュー
Concept: 人気レストランの座席管理
TIME_WAITは「客が帰った後、テーブルを片付けている数分間」に相当する。回転率が高すぎると、空きテーブル(ポート)はあるのに「片付け中(TIME_WAIT)」ばかりで新規客(パケット)を案内できなくなる。tcp_tw_reuseは「片付けがほぼ終わったテーブルを即座に次の客に回す」ルールであり、somaxconnは「店外の待合スペース(キュー)を広げる」改修工事である。
HTTP/1.1や短いKeep-Alive環境下では、大量のTCPコネクションが短期間で生成・破棄される。Linuxのデフォルト設定では、TIME_WAIT状態が一定時間維持されるため、エフェメラルポート(自動割り当てポート)が瞬時に枯渇してしまう。システムコールレベルでコネクションの安全な再利用とキューサイズの拡張を行うことが、高トラフィックを捌くWebサーバーの必須条件となる。
プロダクションレディな sysctl.conf の実装
2026年現在のモダンな環境(Linux Kernel 6.19 / 6.12 LTS および Nginx 1.28.2 安定版)に最適化したカーネルパラメータの実装例を示す。エディタで /etc/sysctl.conf(または /etc/sysctl.d/99-nginx.conf)を開き、以下の設定を適用する。
# /etc/sysctl.conf
# 1. TIME_WAITソケットの再利用(必須)
net.ipv4.tcp_tw_reuse = 1
# 2. キューイング関連の拡張
# Nginxの待ち受けキュー最大値 (Nginx側の backlog= 設定値と合わせる)
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.core.netdev_max_backlog = 65535
# 3. エフェメラルポートの範囲拡大
net.ipv4.ip_local_port_range = 1024 65000
# 4. ファイルディスクリプタ上限の引き上げ
fs.file-max = 1048576
# 設定の反映コマンド: sysctl -p
Watch out for: 過去の古いチューニング記事で頻繁に紹介される net.ipv4.tcp_tw_recycle = 1 は、NAT環境下のクライアントからのパケットドロップを引き起こす致命的な仕様があったため、Linux 4.12以降で完全に廃止(削除)されている。絶対に設定してはならない。また、somaxconnを増やした場合、Nginx側の listen 80 backlog=65535; のようなディレクティブ変更もセットで行う必要がある。
Frequently Asked Questions
Q. 現在のTIME_WAITソケット数を確認するには?
A. ss -ant | awk '{print $1}' | sort | uniq -c または netstat -nat | grep TIME_WAIT | wc -l コマンドを実行することで、TCP状態ごとのソケット数を集計できる。TIME_WAITが数万単位で存在する場合は、チューニングの恩恵が非常に大きい。
Q. カーネルパラメータだけでなく、Nginx側の設定も変更する必要があるか?
A. 必要である。カーネルのファイルディスクリプタ(fs.file-max)や接続キューを引き上げても、Nginx設定(nginx.conf)の worker_rlimit_nofile や worker_connections がデフォルト(通常512や1024)のままでは意味がない。リソースの解放を待たずに処理できるよう、最低でも数万規模に引き上げるべきである。
Q. TCPのTIME_WAIT状態を強制的に0秒(即時破棄)に設定することは可能か?
A. 理論上はRSTパケットを用いて強制切断させるなどの方法があるが、ネットワーク上に遅延パケットが残っていた場合に、後続の別コネクションでデータ破損や通信エラーを引き起こす重大なリスクがある。TCPのプロトコル仕様(RFC)に準拠しつつ、安全な範囲で再利用を許可する net.ipv4.tcp_tw_reuse = 1 に留めるのがベストプラクティスである。
Post a Comment