适用环境:军哥 LNMP(/usr/local/php/)、Nginx + PHP-FPM + MySQL。
目标:让 PHP-FPM 既不因并发不足产生 502/504,也不因进程过多导致内存吃紧或 OOM。
一、两种进程管理模式
| 参数 | 含义 | 适合场景 |
|---|---|---|
pm = static | 固定数量子进程,使用 pm.max_children。 | 流量稳定、内存可控、延迟敏感。 |
pm = dynamic | 按需伸缩,使用 pm.start_servers、pm.min_spare_servers、pm.max_spare_servers。 | 流量波动较大、希望平衡内存与并发。 |
老版本里 dynamic 也叫 apache-like,请以配置文件注释为准。
二、关键参数释义
- pm.max_children:static 下的固定进程数(dynamic 下是上限)。
- pm.start_servers:启动时的子进程数(dynamic)。
- pm.min_spare_servers:最小空闲进程数(dynamic)。
- pm.max_spare_servers:最大空闲进程数(dynamic)。
- pm.process_idle_timeout:空闲进程回收超时,建议 10–30s。
- pm.max_requests:每个子进程处理多少请求后重启,用于缓解内存泄漏(常见 500–5000)。
三、容量规划方法(快速可落地)
- 测算单个 PHP 子进程内存占用:在业务低峰压一次接口,同时执行
ps -o rss,cmd -C php-fpm | awk '{sum+=$1} END{print sum/NR/1024 " MB"}'得到
avg_child_mem(例如 40–80MB)。 - 给 PHP 预留可用内存:
php_mem_budget = 总内存 × 目标比例 - 其他服务保留。- 示例:4GB 机器,给 PHP 预留 2.2GB,Nginx/MySQL/系统保留 1.8GB。
- 计算最大进程:
pm.max_children = floor( php_mem_budget / avg_child_mem )示例:
2200MB / 50MB ≈ 44,取40–44。 - dynamic 推荐初值(经验法则):
pm.start_servers ≈ 0.2 × pm.max_childrenpm.min_spare_servers ≈ 0.1–0.2 × pm.max_childrenpm.max_spare_servers ≈ 0.4–0.6 × pm.max_children
注意:开启 opcache 会显著降低平均内存与 CPU 抖动;大并发上传/图片处理会临时抬升单进程内存,请留安全余量(10–20%)。
四、可直接使用的配置模板(军哥 LNMP)
编辑:/usr/local/php/etc/php-fpm.conf
模板 A:dynamic(推荐大多数网站)
; ====== 基础与日志 ======
error_log = /app/logs/php-fpm.log
log_level = error
events.mechanism = epoll
; 监听与权限(与 Nginx 用户一致)
listen = 127.0.0.1:9000
; 或者:listen = /dev/shm/php-fpm.sock
; listen.owner = www
; listen.group = www
; listen.mode = 0660
; ====== 进程管理 ======
pm = dynamic
pm.max_children = 52 ; 上限(由容量规划得出)
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 25
pm.process_idle_timeout = 20s
pm.max_requests = 2048
; ====== 慢日志 ======
slowlog = /app/logs/$pool.log.slow
request_slowlog_timeout = 10s
; ====== 资源限制 ======
rlimit_files = 32768
request_terminate_timeout = 100s
模板 B:static(低抖动、延迟敏感)
; 仅示例变化部分
pm = static
pm.max_children = 40 ; 固定进程数(容量规划计算值)
pm.max_requests = 2000
pm.process_idle_timeout = 0s
你文中的示例参数(如 pm.max_children = 52、pm.start_servers = 5 等)是合理起点,但请按上文计算法结合同机内存与业务压力调整。
五、应用与验证
# 1) 语法自检
/usr/local/php/sbin/php-fpm -t
# 2) 平滑重载(推荐)
/usr/local/php/sbin/php-fpm -y /usr/local/php/etc/php-fpm.conf -t
kill -USR2 $(cat /usr/local/php/var/run/php-fpm.pid) 2>/dev/null || systemctl reload php-fpm
# 3) 查看进程与监听
ss -lntp | grep php-fpm
ps -ef | grep php-fpm
Nginx 配合(片段):
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000; # 或 unix:/dev/shm/php-fpm.sock
fastcgi_connect_timeout 60;
fastcgi_send_timeout 180;
fastcgi_read_timeout 180;
}
六、常见问题与排错
| 现象 | 可能原因 | 解决 |
|---|---|---|
502/Bad Gateway、日志 connect() failed | PHP-FPM 未启动 / 监听不一致 / 权限不足 | 核对 fastcgi_pass 与 listen;如用 sock,校验 owner/group/mode |
| 504/Gateway Timeout | PHP 执行过久或 Nginx fastcgi 超时偏小 | 优化代码/SQL;提高 fastcgi_read_timeout;调大 request_terminate_timeout |
| 内存飙升/OOM | pm.max_children 过大;脚本内存泄漏 | 重新估算上限;启用 pm.max_requests(1000–3000)并监控 |
| 队列堆积、响应慢 | 并发不足 | 增大 pm.max_children 与 spare;或启用 static,结合压测取点 |
| 慢日志大量记录 | 数据库/外部 API 慢 | 分析 $pool.log.slow,定位瓶颈(索引、连接池、网络) |
七、调优建议清单
- 开启 opcache(
opcache.enable=1,opcache.memory_consumption=128–256)。 - 静态资源走 Nginx,PHP 勿做文件直传;上传用分片或异步后端。
- 压测找“拐点”:逐步提高并发,观察 QPS、P95 延迟与 RSS/CPU 曲线。
- 记录基线:变更前后保留
nginx access_log、php-fpm.log、系统监控。
附:你给出的示例参数说明(对照)
/usr/local/php/etc/php-fpm.conf
error_log = /app/logs/php-fpm.log
log_level = error
events.mechanism = epoll
listen.owner = www
listen.group = www
pm.max_children = 52
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 25
pm.process_idle_timeout = 20s
pm.max_requests = 2048
slowlog = /app/logs/$pool.log.slow
rlimit_files = 32768
request_terminate_timeout = 100s
request_slowlog_timeout = 10s
查看进程:
ps -ef | grep fpmFAQ
Q1:static 还是 dynamic 更好?
低抖动、延迟敏感、内存充足选 static;一般业务/流量有波动选 dynamic。核心仍是正确的容量规划。
Q2:pm.max_requests 设多少合适?
1000–3000 为常见区间;越大重启越少,越小更能抑制泄漏。结合慢日志与 RSS 曲线调节。
Q3:如何快速估算 pm.max_children?
用经验值 40–60MB/进程保守估算:上限 ≈ 可用内存(MB) / 50,上线后再根据实测 RSS 调整。






