Nginx 与 PHP-FPM 调优实战:从 502、499 与排队现象反推问题层
调优的起点是先判断请求卡在连接层、PHP-FPM 进程池还是应用下游,再每次只改一个参数并用同一时间窗口对照验证;本文不含实测数据与推荐数值,参数取值需按自身环境核实。
Nginx 与 PHP-FPM 调优最常见的做法,是直接抄一组 worker_processes 和 pm.max_children 的数值。这些数值是否合适,取决于机器内存、单请求常驻内存、流量形态与下游耗时,通用数字必须在自己的环境里复现才有意义。本文没有可核验的测试记录,也未运行任何压测,因此不给性能数字,也不给“最优参数”;只提供一套分层定位方法:先确认请求卡在哪一层排队,再决定改什么。
一个 PHP 请求至少经过三段排队#
- 连接层:Nginx 接收连接、完成 TLS 握手、等待空闲 worker 处理,受 worker 进程数与连接数上限约束。
- 进程池:请求被转发给 PHP-FPM 后,等待一个空闲 worker 进程。这里排队,改 Nginx 参数通常无效。
- 下游:PHP 进程内访问数据库、缓存或外部 HTTP 接口,耗时计入上游响应时间,与前两层无关。
先打开两个状态入口#
定位的前提是能看到排队情况。下面是示意配置,未在本环境执行,指令拼写与模块可用性请对照所使用版本的官方文档核实,路径与访问控制按实际部署调整。
# Nginx:示意配置,未执行
location = /status {
stub_status;
allow 127.0.0.1;
deny all;
}
; php-fpm pool 配置:示意,未执行
pm.status_path = /fpm-status
同时在 Nginx 的访问日志格式里保留 $request_time 与 $upstream_response_time,这两个值是后面区分层次的主要依据。
用三类信号判断层,而不是猜#
| 信号 | 位置 | 判读方向 |
|---|---|---|
| reading / writing / waiting 连接数 | Nginx stub_status | waiting 偏高通常对应 keepalive 空闲连接,需结合并发与流量形态看,单独一个数字不构成结论。 |
| listen queue、active processes、max children reached | PHP-FPM status | 队列持续非零且 reached 计数增长,说明请求在进程池排队,此时应先查进程池与单请求耗时。 |
$request_time 与 $upstream_response_time 的差值 | Nginx 访问日志 | 两者接近说明时间花在 FPM 及其下游;差值大说明时间花在 Nginx 侧、客户端侧或响应传输上。 |
表中不列阈值:什么算“偏高”,取决于业务可接受的延迟与机器余量,需要自己用同一时间窗口的对照数据确定。
两个容易走错方向的现场#
出现 502 就加 worker_processes
502 表示 Nginx 没能从上游拿到有效响应。若 FPM status 里同时看到队列堆积或 reached 增长,瓶颈在进程池,加 Nginx worker 只会让更多请求更快地涌向已经排满的进程池。反过来,若队列为空而 502 仍出现,才需要看 FPM 是否在重启、socket 是否可达。
把 499 当成服务端错误
499 是 Nginx 记录“客户端在响应返回前关闭连接”的状态码,反映的是总时长超出了客户端或调用方的等待预算。它指向缩短端到端耗时或重新核对超时设置,而不是简单增加进程数。
一次只改一个参数,并留下对照窗口#
- 固定观测范围:同一路径、同一时长窗口、同一流量水平。
- 记录改动前后的 p95 延迟、5xx 与 499 计数、FPM 队列峰值、CPU 与内存占用。
- 一次只动一个参数,改动后至少跑满一个完整窗口再比较。
- 没有对照窗口的改动不算验证,只能算尝试。
如果 PHP 代码里还会同步调用外部 HTTP 接口(例如通过 API.PLUS 这类第三方服务),这段耗时同样计入 $upstream_response_time。此时调 Nginx 或 FPM 参数不会缩短它,需要单独测量外部调用的耗时分布。
边界与待核实项#
- OPcache 是否启用、静态资源是否由 Nginx 直接返回、FPM 的进程管理方式选 static 还是 dynamic,都会改变上述信号的解读,需按自身流量形态核实。
- 各参数的具体取值、以及本文方法在当前版本上的适用性,均待核实;本文未执行任何测试,不提供性能结论。
可复用的结论只有一条:先让“哪一层在排队”有观测依据,再让每一次改动都能被同一窗口的数据支持或否定。参数表可以后补,归因链条断掉之后,调优就退化成反复试错。