本文最初写于2017年,2026年根据PHP官方文档重新整理。

PHP-FPM是FastCGI进程管理器,以Nginx和PHP的常见组合为例,Nginx接收HTTP请求,将需要PHP处理的部分通过FastCGI交给FPM。FPM管理一组worker进程,每个worker在同一时刻处理一个请求。

worker太少会让请求排队,太多又可能耗尽内存或引发更严重的资源竞争,配置时需要同时考虑这两头。

master与worker

FPM启动后由master进程管理pool和worker。master负责进程生命周期、配置和信号处理,worker负责执行具体的PHP请求。

不同pool可以使用不同的用户、监听地址和进程参数,从而隔离不同应用。但pool增多并不会创造额外资源,所有worker最终仍然共享机器的CPU、内存和I/O能力。

三种进程管理模式

FPM通过pm选择worker数量的管理方式。

static

始终保持pm.max_children个worker。数量固定、行为容易预估,适合流量稳定且资源预算明确的服务。

dynamic

启动时创建pm.start_servers个worker,再根据空闲进程数量,在pm.min_spare_servers、pm.max_spare_servers和pm.max_children约束下动态增减。

它适合有波动但仍希望保留一定预热能力的场景。

ondemand

启动时不预先创建worker,请求到来时再生成,空闲时间超过pm.process_idle_timeout后退出。它可以减少低频服务的常驻内存,但冷启动和突发流量下的进程创建成本需要纳入考虑。

如何确定worker数量

pm.max_children限制可以同时处理的请求数。它不应从网上复制一个固定值,而应结合实际观测:

  1. 测量真实业务worker的平均和高位内存占用。
  2. 为操作系统、Nginx、日志和其他服务预留内存。
  3. 用可分配给FPM的内存除以单个worker的高位占用,得到初步上限。
  4. 再通过压测和线上延迟、队列、CPU与数据库连接情况校正。

内存允许不等于下游能够承受。worker增加后,数据库连接、缓存请求和外部调用也会同时增加。

比进程数更重要的观测

实际运行中至少应该关注:

  • 活跃、空闲和总worker数量。
  • 是否频繁达到pm.max_children。
  • 请求排队和响应时间。
  • 慢请求及其调用栈。
  • worker内存是否随请求持续增长。

pm.max_requests可以让worker处理一定请求后重启,对第三方库的内存泄漏具有缓解作用,但它不能替代定位泄漏原因。

调整worker数量时,需要同时看内存预算、下游容量和请求排队情况,不能只看进程能不能启动。

参考