tcp_max_tw_buckets单独调大无效,必须与tcp_tw_reuse=1、tcp_timestamps=1、ip_local_port_range扩容、fastcgi_keep_conn on五项协同生效,否则Nginx代理PHP-FPM时高并发短连接会迅速耗尽端口。

直接说结论:tcp_max_tw_buckets 单独调大没用,必须和 tcp_tw_reuse=1、tcp_timestamps=1、ip_local_port_range 扩容、fastcgi_keep_conn on 这五项一起生效,否则 Nginx 代理后端 PHP-FPM 时,每秒几百次短连接就会快速耗尽端口。
为什么 Nginx + PHP-FPM 容易触发 TIME_WAIT 堆积
Nginx 默认用短连接转发请求到 PHP-FPM(尤其是 TCP 模式),每个请求走完就 close(),而 Linux 内核会将该 socket 置为 TIME_WAIT 状态并维持 60 秒(2MSL)。高并发下,哪怕 QPS 只有 300,每秒也会新增 300 个 TIME_WAIT 条目;若持续 2 分钟,就可能堆积超 3.6 万个——已逼近默认 tcp_max_tw_buckets=32768 阈值。
常见错误现象包括:
-
Cannot assign requested address报错,Nginx 日志里却只显示upstream timed out或无明确错误 -
ss -tan state time-wait | wc -l稳定在 5 万+,但netstat -s | grep "time wait bucket"显示time wait bucket table overflow计数持续增长 - PHP-FPM 日志正常,
php-fpm.status显示空闲进程充足,但 Nginx 响应延迟飙升
必须同步配置的五个关键参数
这五项不是“可选优化”,而是构成闭环的最小可行集。漏掉任意一项,其他都可能失效或引发新问题。
立即学习“PHP免费学习笔记(深入)”;
-
net.ipv4.tcp_tw_reuse = 1:允许本机(Nginx)复用处于 TIME_WAIT 的本地端口发起新连接,对fastcgi_pass 127.0.0.1:9000类型的 outbound 请求直接生效 -
net.ipv4.tcp_timestamps = 1:tcp_tw_reuse的硬性前提,防止 PAWS(Protect Against Wrapped Sequence numbers)误判;现代内核默认开,但必须显式写入/etc/sysctl.conf -
net.ipv4.ip_local_port_range = 1024 65535:扩大可用临时端口池。若仍用默认32768 65535(仅约 3.2 万端口),再怎么调tcp_max_tw_buckets也无意义 -
net.ipv4.tcp_max_tw_buckets = 262144:设为 256K 是高并发网关的稳妥起步值;若实测ss -tan state time-wait | wc -l的 95 分位 > 180000,可升至524288 -
fastcgi_keep_conn on:在 Nginx 的location ~ \.php$块中启用,让 Nginx 复用与 PHP-FPM 的连接(需 PHP-FPM 同步配listen.backlog = 512)
PHP-FPM 和 Nginx 的配套行为调整
内核参数只能缓解,真正减少 TIME_WAIT 生成量,得从连接使用方式入手。重点不在“删”,而在“省”和“复用”。
- PHP-FPM 必须用
listen = /var/run/php-fpm.sock(Unix Socket)而非127.0.0.1:9000(TCP):Unix Socket 不走网络协议栈,不产生 TIME_WAIT - 若必须用 TCP(如跨主机部署),则 Nginx upstream 中要加
keepalive 32,且 PHP-FPM 的listen.backlog至少设为512,避免 accept 队列溢出 - Nginx 的
keepalive_timeout建议设为65,keepalive_requests设为1000,确保客户端 HTTP 连接复用,减少 Nginx 自身新建连接频次 - 禁用
net.ipv4.tcp_tw_recycle = 0(必须显式设为 0):该参数在任何含 NAT 的环境(包括云厂商 SLB、K8s Service、家用路由器)都会导致连接失败,Linux 4.12+ 已移除
容易被忽略的验证点和坑
调完不验证,等于没调。最常被跳过的三件事:
- 改完
/etc/sysctl.conf后,必须执行sysctl -p,不能只改文件;检查是否生效用sysctl net.ipv4.tcp_tw_reuse -
fastcgi_keep_conn on仅在fastcgi_pass指向 Unix Socket 时才真正起效;指向 TCP 地址时,它控制的是 Nginx 与 upstream 的连接复用,和 TIME_WAIT 无关 - PHP 应用层若用了
curl_close()或未复用cURL handle,每次请求都新建 TCP 连接到第三方服务,这部分 TIME_WAIT 完全不受 Nginx 参数影响——得查应用代码
真正卡住的,往往不是参数设错,而是某一层的连接复用没打开,或者某个组件悄悄关闭了 keepalive。



















