必须用php-fpm:因其支持平滑重启、动态伸缩、慢日志、内存限制等企业级功能;php-cgi无进程复用致资源耗尽,mod_php不兼容nginx,二者均无法满足高并发稳定运行需求。

直接说结论:PHP 必须用 php-fpm 独立进程管理,不能用 mod_php(Apache 风格)或 php-cgi 直接调用——否则高并发下会卡死、502 暴增、内存失控。
为什么必须用 php-fpm 而不是其他方式
Nginx 本身不解析 PHP,它只负责转发请求。能和 Nginx 安全高效配合的只有 php-fpm,因为:
-
php-fpm是专为 FastCGI 协议设计的进程管理器,支持平滑重启、动态子进程伸缩、慢日志、内存限制等企业级功能 -
php-cgi每次请求都 fork 新进程,无进程复用,CPU 和内存开销极大,ps aux | grep php一看就是几百个僵尸进程 -
mod_php是 Apache 的模块,Nginx 根本不支持加载它;强行编译或配置只会报unknown directive "php_flag"或直接启动失败 - 所有主流发行版(CentOS/Rocky/Alibaba Cloud Linux)的
php-fpm包默认已启用systemd管理,systemctl status php-fpm可实时查看运行状态
php-fpm 配置里最容易被改错的三个参数
很多人照抄网上配置,把 /etc/php-fpm.d/www.conf 改得面目全非,结果上线后 CPU 100% 或 502 频发。关键就在这三处:
-
pm = dynamic—— 不要用static。小服务器(2G 内存)建议设pm.max_children = 20,大一点(4G+)可到 32~48;设太高会导致 OOM killer 杀进程 -
pm.max_requests = 1000—— 必须设!防止 PHP 扩展内存泄漏累积(尤其 GD、cURL 类扩展),不设等于放任进程越跑越胖 -
listen = /run/php-fpm/www.sock—— 推荐 Unix socket,比127.0.0.1:9000少一层 TCP 协议栈开销;但要注意 Nginx 配置中fastcgi_pass必须路径一致,且nginx用户需对/run/php-fpm/有读写权限(chown nginx:nginx /run/php-fpm)
Nginx 转发 PHP 请求时最常漏掉的两件事
哪怕 php-fpm 跑着,Nginx 也正常,但访问 index.php 还是 502 或直接下载源码——问题几乎都出在下面这两点:
- 没加
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;。缺这行,php-fpm根本不知道要执行哪个文件,日志里会反复出现Primary script unknown - 没配
location ~ \.php$块,或者正则写成location \.php$(少了~),导致 Nginx 把.php当作静态文件直接返回,浏览器就下载源码 - 额外提醒:
root指令必须写在server块里,不能只写在location里;否则$document_root解析为空,SCRIPT_FILENAME拼出来就是错的
验证是否真跑通了 PHP 独立环境
别只靠 curl http://127.0.0.1/info.php 看页面——那只能说明 PHP 解析了,不能说明是 php-fpm 在管、且和 Nginx 链路干净。要这样查:
- 执行
sudo ss -tuln | grep ':9000\|php-fpm',确认php-fpm确实在监听 socket 或端口 - 访问一个故意写错的 PHP 文件(比如
test.php里写<?php foo(); ?>),看 Nginx 错误日志/var/log/nginx/error.log是否出现FastCGI sent in stderr—— 有,说明链路通;没有,说明根本没转给php-fpm - 用
ab -n 100 -c 10 http://127.0.0.1/info.php压测,再立刻执行sudo systemctl status php-fpm,观察Active: active (running)下面的进程数有没有波动,没波动=没真正接入
真实生产环境里,php-fpm 的 slowlog 和 Nginx 的 upstream timed out 日志,往往比错误本身更早暴露瓶颈。别等 502 爆了才去看。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











