通过对比 $request_time 与 $upstream_response_time 可精准定位 FastCGI 瓶颈:若两者接近(如均≈800ms),问题在 PHP-FPM 内部;若 $request_time 明显更大(差值>200ms),瓶颈在 Nginx 层或网络链路。

直接看 Nginx access.log 里的 $request_time 和 $upstream_response_time,就能快速定位 FastCGI(如 PHP-FPM)的瓶颈在哪一环——不是靠猜,而是靠这两个字段的差值说话。
盯住两个关键时间字段的含义
$request_time 是从客户端发第一个字节,到 Nginx 把响应全部发完的总耗时。它包含:
– 客户端上传时间(尤其大 POST 或弱网)
– Nginx 自身处理(rewrite、gzip、日志写入等)
– FastCGI 请求转发 + 等待响应 + 下发响应体的时间
$upstream_response_time 是 Nginx 与 PHP-FPM 建立连接后,到收到完整 FastCGI 响应头(或响应体)所花的时间。它只反映 PHP-FPM 的实际执行耗时,不含网络往返和 Nginx 开销。
若两者接近(比如都 ≈800ms),问题基本在 PHP-FPM 内部;若 $request_time 明显更大(差值 >200ms),瓶颈更可能出在 Nginx 层或网络链路。
用日志快速识别 PHP-FPM 慢请求模式
- 查最慢的 FastCGI 请求(假设最后两列是 $upstream_response_time 和 $request_time):
awk '$(NF-1) != "-" && $(NF-1) > 0.5 {print $(NF-1), $0}' access.log | sort -k1nr | head -10 - 统计超 500ms 的 PHP 接口分布:
awk -F'"' '$(NF-1) > 0.5 {print $2}' access.log | cut -d' ' -f2 | sort | uniq -c | sort -nr - 关注状态码为 200 但 $upstream_response_time 高的请求,排除 502/504 干扰,专注“成功但慢”的真实业务逻辑问题
结合 PHP-FPM 自身指标交叉验证
仅靠 Nginx 日志不够,要联动 PHP-FPM 的运行状态:
- 启用
pm.status_path = /status并配置 Nginx location 代理访问,可实时看到 active processes、max children exceeded、slow requests 等关键指标 - 开启
slowlog(如slowlog = /var/log/php-fpm-slow.log),配合request_slowlog_timeout = 1s,精准捕获执行超时的 PHP 脚本 - 检查
access.log中是否出现大量upstream: "fastcgi://127.0.0.1:9000"对应的高耗时,再比对php-fpm.log是否有子进程重启、OOM 或 accept() 失败记录
排查常见 FastCGI 性能陷阱
-
进程池打满:Nginx 日志中 $upstream_response_time 出现大量 “-” 或突增到 timeout 值(如 30s),同时 PHP-FPM status 显示
max children exceeded,说明 pm.max_children 设置过小 - IO 阻塞严重:slowlog 中反复出现数据库查询、curl 同步调用、file_get_contents 读大文件等,需异步化或加缓存
-
FastCGI 连接配置不合理:Nginx 的
fastcgi_read_timeout小于 PHP-FPM 的request_terminate_timeout,导致提前断连;或fastcgi_buffers过小,频繁刷盘拖慢响应 - PHP 扩展或代码级问题:启用 xdebug 未关闭、serialize/unserialize 大数组、未关闭的 GD 图像资源,都会抬高 $upstream_response_time



















