php-fpm主进程仅负责监听、fork子进程和监控worker,不执行php脚本;所有请求由worker进程独立处理,每个worker单线程阻塞式服务一个请求,其并发能力等于存活worker数。

PHP-FPM主进程不处理请求,只管调度和回收
很多人误以为php-fpm主进程会参与执行PHP脚本,其实它完全不碰业务逻辑。主进程(Master)只做三件事:监听listen配置的Socket或端口、按需fork子进程、监控子进程状态并拉起崩溃的worker。所有HTTP请求的实际解析、脚本执行、扩展加载,都由worker进程独立完成。
常见错误现象是看到ps aux | grep php-fpm里出现多个php-fpm: pool www进程,就以为主进程也在跑PHP——其实那些全是worker,主进程通常显示为php-fpm: master process,且CPU占用极低。
- 主进程不读取
php.ini或执行代码,它只加载FPM自身配置(如/etc/php-fpm.conf) - worker进程启动时才加载
php.ini和池配置(如/etc/php-fpm.d/www.conf),每个worker拥有独立内存空间 - 主进程通过共享内存(而非IPC通信)获取worker状态,比如
pm.status_path暴露的统计信息就来自这里
worker进程是单线程阻塞模型,一个进程同一时间只服务一个请求
PHP-FPM的worker不是事件驱动,也不用协程或线程池。每个worker启动后调用fcgi_accept_request(),然后阻塞等待下一个FastCGI请求到来;收到请求→解析→执行PHP→返回响应→再回到fcgi_accept_request()等待下一次。这意味着:
如果你在脚本里写sleep(10),这个worker在这10秒内完全无法响应其他请求,哪怕队列里堆了100个待处理连接。
- worker并发能力 = 当前存活的worker数量,和CPU核心数无关(不像Node.js或Go)
-
pm.max_children设得过高,会导致内存耗尽;设得太低,高并发时大量请求卡在master的accept队列里,触发Nginx的502 Bad Gateway - worker不会“复用”连接,但会复用PHP解释器实例——避免每次请求都重新加载扩展和OPcache,这是性能关键
进程生命周期由pm模式决定,dynamic最常用但配置不当易抖动
pm参数不是随便选的。static模式固定worker数,适合负载稳定的小站;ondemand模式按需启停,冷启动延迟明显;dynamic是多数生产环境的选择,但它依赖三个联动参数:
-
pm.start_servers:启动时预建worker数,应略高于平均并发量 -
pm.min_spare_servers和pm.max_spare_servers:空闲worker数量阈值,超出范围就会kill或fork新进程 -
pm.max_children:硬上限,一旦达到,新请求会被master丢弃(Nginx报502)
容易踩的坑是把pm.min_spare_servers设得太小(比如1),流量突增时worker来不及扩容,大量请求排队超时;或者pm.max_children算错内存,比如每个worker占128MB,服务器总内存2GB,却设成32,实际可能因系统预留和其他进程导致OOM。
listen.backlog和request_terminate_timeout共同影响连接堆积行为
当所有worker忙完,新来的FastCGI连接不会立刻被拒绝,而是由内核TCP层暂存——这个缓冲区长度由listen.backlog控制(默认65535,但受系统net.core.somaxconn限制)。而request_terminate_timeout决定了worker处理单个请求的最长容忍时间。
如果一个PHP脚本卡死(比如MySQL死锁未设timeout),worker会一直占着不释放,直到request_terminate_timeout触发强制kill。此时该worker退出,主进程补一个新的,但期间堆积的连接可能已超listen.backlog,新连接直接被内核丢弃,Nginx日志里出现connect() failed (111: Connection refused) while connecting to upstream。
-
listen.backlog值建议设为pm.max_children + 10左右,避免连接丢失 -
request_terminate_timeout必须小于Nginx的fastcgi_read_timeout,否则Nginx先超时断连,FPM还不知道 - 真正定位卡死请求靠
slowlog,而不是等timeout——它记录的是执行超过request_slowlog_timeout的完整backtrace
pm.status_path、slowlog和netstat -lnp | grep :9000一起看。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











