用户登录

技术文章

外部链接将在新标签页打开。

Nginx 与 PHP-FPM 调优先算什么:进程池容量、超时链与变更顺序

一句话回答

Nginx 与 PHP-FPM 调优不应从改参数开始,而应先分层定位瓶颈,再把进程池容量换算成内存与后端并发预算,并按“内层先失败”的原则对齐超时链;具体数值必须在目标环境压测后确定,本文不含实测结论。

先给结论:在没有可比基线的前提下,Nginx 与 PHP-FPM 的“调优”不该从改参数开始,而应先做三件事:确认瓶颈在哪一层、把进程池容量换算成内存与后端并发预算、把 Nginx 到 FPM 的超时链按“内层先失败”对齐。本文不含实测数字:本次没有可用的正文素材,也没有可核验的压测记录,因此所有取值都要在你的目标环境测量后确定,参数名与默认值请以所部署版本的官方文档为准(待核实)。文中配置片段均为未执行的占位示例。

一、先判断瓶颈在哪一层,而不是先加进程#

一个 PHP 请求在链路上至少经过四段:Nginx 连接与 worker、FastCGI 排队与 PHP-FPM 进程池、PHP 脚本执行、脚本调用的外部依赖(数据库、缓存、HTTP 接口)。四段的失败表现不同,混在一起看会得出错误结论。

  • 连接层:Nginx 侧连接被拒或排队,通常指向 worker 连接上限、文件描述符或内核队列。
  • 进程池层:请求在 FPM 侧等待空闲进程,表现为延迟上升但 CPU 不高。
  • 执行层:脚本本身的 CPU 或内存消耗,可用慢日志定位。
  • 依赖层:脚本在等外部响应,FPM 进程被长时间占住。

判断依据应来自你自建的观测:Nginx 的访问与错误日志、PHP-FPM 进程池状态页、慢请求日志、以及系统层的 CPU、内存、负载与连接数。状态页需在进程池配置中显式开启,具体指令与字段随版本而异,请按版本文档核对,不要照抄他人配置。

二、把进程池参数换算成资源等式#

PHP-FPM 的 pm.max_children 决定同一时刻最多有多少个子进程处理请求,它同时受两侧约束:

  • 内存侧:max_children × 单进程常驻内存 ≤ 为 PHP 预留的内存预算。单进程内存必须实测,不同框架差异很大,本文不给数字。
  • 下游侧:max_children × 每请求持久的数据库连接数 ≤ 数据库可承受的连接上限。进程池放宽后,压力会原样传导到下游。

因此“加大 max_children 后变快”往往只是把排队从 FPM 挪到了数据库。如果慢的根因是 SQL 或外部接口,扩大进程池只会放大并发、加重下游负担。pm.max_requests 用于周期性回收进程,取值需要权衡内存泄漏与重启开销;pm 采用 static、dynamic 还是 ondemand,取决于流量是否平稳,这一点同样需要你的流量曲线来定。

; 占位示例,未在目标环境执行;数值须由压测与内存测量确定
pm = dynamic
pm.max_children = YOUR_MAX_CHILDREN
pm.start_servers = YOUR_START_SERVERS
pm.max_requests = YOUR_MAX_REQUESTS
request_terminate_timeout = YOUR_SECONDS

三、超时链要对齐,让内层先失败#

很多“调优后更慢”的案例,本质是超时配置互相矛盾:Nginx 先超时返回 504,但 PHP 进程仍在校验、写入或重试,资源被继续占住。原则是外层超时不短于内层,并让失败点能留下可归因的日志。

层常见参数(按版本文档核对)期望的失败顺序
PHP 脚本max_execution_time、set_time_limit最先触发
FPM 进程池request_terminate_timeout脚本超时后的后备措施
Nginx → FPMfastcgi_connect_timeout、fastcgi_read_timeout最后触发,返回 504 并写错误日志
上游客户端业务侧 HTTP 客户端超时与最内层保持一致

注意 max_execution_time 在不同 SAPI 下的计时范围并不相同,具体行为请查对应版本文档(待核实)。若脚本里有阻塞式外部调用,脚本超时可能无法及时中断,此时应以客户端超时为主。

# 占位示例,未执行
location ~ \.php$ {
    fastcgi_connect_timeout YOUR_CONNECT_SECONDS;
    fastcgi_read_timeout    YOUR_READ_SECONDS;
    fastcgi_pass unix:/YOUR_SOCKET_PATH;
}

四、变更顺序与实验边界#

  1. 记录基线:固定负载模型(并发数、请求分布、数据规模),记录 p95 延迟、错误率与各层资源占用。
  2. 一次只改一个维度:容量、超时、还是应用层缓存,分开改才可归因。
  3. 同负载复测并保存原始数据;没有复测的“感觉变快了”不算结论。
  4. 准备回滚:配置变更前留存原文件,并明确回滚判据(例如错误率超过基线多少即回退)。

篇幅与素材所限,本文只能提供方法与边界,不能提供“某参数设为某值”的通用答案。若你需要一组可直接上线的数值,需要先补齐两样东西:目标环境的单进程内存测量值,以及下游系统的连接上限。

作者:沐小悠

本文约 6 分钟读完 · 关键词:Nginx 调优、PHP-FPM、pm.max_children、fastcgi_read_timeout、容量估算

更多文章 GET 示例接口

「」标签下的其他文章