phpEnv中Nginx长连接生效需同步配置upstream keepalive、fastcgi_http_version 1.1和fastcgi_set_header Connection '',仅调大keepalive_timeout无效;否则Nginx到PHP-FPM仍频繁新建连接。

phpEnv 的 Nginx 长连接不能只改 keepalive_timeout,必须同步配 upstream 的 keepalive、协议版本和 Connection 头清理,否则配置无效。
phpEnv 中 Nginx 的 keepalive_timeout 不是唯一关键参数
phpEnv 默认的 Nginx 配置里,keepalive_timeout 通常设为 60 或 75 秒,这仅控制「客户端到 Nginx」这一段的长连接保持时间。它对「Nginx 到后端 PHP-FPM 或其他 upstream 服务」完全不起作用——那段连接由 upstream 块里的 keepalive 指令控制。
常见错误现象:
- 浏览器 Network 面板看到 client→Nginx 是复用的(Connection: keep-alive),但后端日志或
ss -tnp | grep :9000显示 PHP-FPM 连接频繁新建、TIME_WAIT 爆增 - 压测时 QPS 上不去,
nginx -t通过,但实际连接数远超预期
真正起效的配置点在 upstream php_backend { ... } 块内,不是全局 http 块。
立即学习“PHP免费学习笔记(深入)”;
upstream 块必须显式启用 keepalive 并匹配 PHP-FPM 容量
phpEnv 默认不写 upstream,多数用户直接用 fastcgi_pass 127.0.0.1:9000,这种写法会禁用长连接。你得手动补全 upstream 块,并注意三点:
- 把
fastcgi_pass改成指向 upstream 名,例如fastcgi_pass php_backend; -
keepalive值不能拍脑袋:PHP-FPM 默认pm.max_children = 50,每个 worker 进程最多处理 1 个请求,所以整个池子最多并发 50 连接;若 Nginx 有 4 个 worker,keepalive 32就已超限(4×32=128 > 50);建议设为keepalive 10~12 - 必须加
keepalive_requests 1000和keepalive_timeout 60s,否则单连接复用次数太少或空闲即断
示例片段(放在 http 块内):
upstream php_backend {
server 127.0.0.1:9000;
keepalive 12;
keepalive_requests 1000;
keepalive_timeout 60s;
}
location 中必须强制 HTTP/1.1 + 清空 Connection 头
即使 upstream 配了 keepalive,如果 location 里没声明协议版本或透传了 Connection: close,Nginx 仍会每次新建连接。phpEnv 的默认 fastcgi_params 文件通常不含这些,需手动补:
-
fastcgi_http_version 1.1;(不是proxy_http_version,这是 FastCGI 场景) -
fastcgi_set_header Connection '';—— 注意是空字符串,不是keep-alive,也不是close - 确认
fastcgi_param SCRIPT_FILENAME等基础参数仍在生效,避免因覆盖丢失
错误写法:fastcgi_set_header Connection "keep-alive"; → 后端 PHP-FPM 会忽略该头,且可能触发兼容性问题。
验证是否真复用:别信配置,要看连接状态
改完重启 Nginx(phpenv nginx restart),立刻验证,而不是等上线后排查:
- 发起持续请求:
for i in {1..200}; do curl -s http://localhost/test.php > /dev/null; done - 查 Nginx 到 PHP-FPM 的真实连接数:
ss -tnp | grep ':9000' | grep 'ESTAB' | wc -l,稳定在keepalive × worker_processes附近(如 12×2=24)才算成功 - 查 PHP-FPM 当前活跃进程:
sudo /path/to/php-fpm-status?full(需开启 status),看active processes是否明显低于未优化前 - 抓包确认响应头不含
Connection: close,且复用同一 socket(Wireshark 过滤tcp.stream eq N)
最容易被忽略的是:phpEnv 的 Windows 版本中,ss 不可用,得用 netstat -ano | findstr :9000 | findstr ESTABLISHED 替代,且要注意防火墙可能隐藏本地回环连接。



















