你的 PHP 应用上线后,QPS 上不去?响应时间长?很可能是 PHP-FPM 配置不合理。
今天聊聊 PHP-FPM 的工作原理和调优技巧。
PHP-FPM 是什么
PHP-FPM(FastCGI Process Manager)是 PHP 的进程管理器,负责:
- 接收 Web 服务器(Nginx/Apache)转发的请求
简单说,Nginx 收到 PHP 请求后,转给 PHP-FPM,PHP-FPM 分配一个子进程执行 PHP 代码,返回结果。
核心配置文件
- 主配置:
/etc/php-fpm.conf 或 /etc/php/8.x/fpm/php-fpm.conf - 进程池配置:
/etc/php-fpm.d/www.conf 或 /etc/php/8.x/fpm/pool.d/www.conf
进程管理模式
PHP-FPM 有三种进程管理模式:
1. static(静态)
pm = staticpm.max_children = 50
固定数量的子进程,不会动态增减。
2. dynamic(动态,默认)
pm = dynamicpm.max_children = 50pm.start_servers = 5pm.min_spare_servers = 5pm.max_spare_servers = 35
根据负载动态调整进程数。
min_spare_servers:最少空闲进程数
max_spare_servers:最多空闲进程数
3. ondemand(按需)
pm = ondemandpm.max_children = 50pm.process_idle_timeout = 10s
没有请求时不创建进程,有请求才创建。
关键参数调优
1. max_children 计算
公式:max_children = 可用内存 / 单个进程内存
查看单个 PHP 进程内存:
ps aux | grep php-fpm | awk '{sum+=$6; count++} END {print sum/count/1024 "MB"}'
假设:
max_children = (8 - 2) * 1024 / 50 ≈ 120
保守一点,设置 100。
2. request_terminate_timeout
pm.request_terminate_timeout = 30s
单个请求最大执行时间,超时会被杀掉。防止慢请求占用进程。
3. max_requests
pm.max_requests = 500
每个进程处理多少请求后重启。防止内存泄漏。
4. 慢日志
slowlog = /var/log/php-fpm/slow.logrequest_slowlog_timeout = 3s
超过 3 秒的请求会记录到慢日志,方便排查性能问题。
完整配置示例
8GB 内存服务器,中等流量:
[www]user = www-datagroup = www-datalisten = /run/php/php8.2-fpm.socklisten.owner = www-datalisten.group = www-datalisten.mode = 0660; 进程管理pm = dynamicpm.max_children = 100pm.start_servers = 20pm.min_spare_servers = 10pm.max_spare_servers = 50pm.max_requests = 500; 超时设置request_terminate_timeout = 30srequest_slowlog_timeout = 3sslowlog = /var/log/php-fpm/slow.log; 状态页pm.status_path = /fpm-statusping.path = /fpm-pingping.response = pong
高流量场景(16GB 内存):
pm = staticpm.max_children = 200pm.max_requests = 1000
监控 PHP-FPM 状态
开启状态页后,配置 Nginx:
location /fpm-status { fastcgi_pass unix:/run/php/php8.2-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; allow 127.0.0.1; deny all;}
访问 /fpm-status?full 查看详细状态:
pool: wwwprocess manager: dynamicstart time: 01/Jan/2024:00:00:00start since: 86400accepted conn: 123456listen queue: 0max listen queue: 10listen queue len: 128idle processes: 20active processes: 5total processes: 25max active processes: 50max children reached: 0
关键指标:
Nginx 配置优化
location ~ \.php$ { fastcgi_pass unix:/run/php/php8.2-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; # 超时设置 fastcgi_connect_timeout 60s; fastcgi_send_timeout 60s; fastcgi_read_timeout 60s; # 缓冲设置 fastcgi_buffer_size 64k; fastcgi_buffers 4 64k; fastcgi_busy_buffers_size 128k;}
常见问题排查
1. 502 Bad Gateway
原因:PHP-FPM 进程不够或挂了
检查:
2. 504 Gateway Timeout
原因:PHP 执行超时
检查:
- 检查 request_terminate_timeout
- 检查 Nginx 的 fastcgi_read_timeout
3. 内存不足
原因:max_children 设置过大
解决:
性能测试
用 ab 或 wrk 测试:
# ab 测试ab -n 10000 -c 100 http://localhost/api/test# wrk 测试wrk -t4 -c100 -d30s http://localhost/api/test
调整参数后对比 QPS 和响应时间。
总结
PHP-FPM 调优要点:
- ✅ 流量稳定用 static,波动用 dynamic
- ✅ 监控状态页,关注 listen queue 和 max children reached
调优是个持续过程,要根据实际监控数据不断调整。
下一篇进入面向对象进阶,聊聊 Trait 的正确用法。