根本原因是Nginx与PHP-FPM连接模型不匹配:宝塔默认TCP通信(127.0.0.1:9000),而PHP-FPM的listen.backlog默认仅64,高并发时请求被内核队列丢弃导致502,并非PHP处理能力不足。

为什么改了 worker_processes 和 pm.max_children 还是 502?
根本原因不是参数没调,而是 Nginx 与 PHP-FPM 的连接模型不匹配。Nginx 默认用 fastcgi_pass 走 Unix socket 或 TCP,但宝塔默认配的是 127.0.0.1:9000,而 PHP-FPM 的 listen.backlog(内核连接队列长度)默认只有 64,高并发时请求直接被丢弃,Nginx 就报 502。这不是 PHP 处理不过来,是根本没进 PHP。
-
worker_processes建议设为 CPU 核心数(auto即可),别盲目设成 64 —— 多余的 worker 不提升吞吐,反而争抢锁 -
worker_connections在宝塔里对应「Nginx 配置 → 全局 → 工作进程最大连接数」,单机压测建议 4096~8192,但必须同步调大系统net.core.somaxconn(至少 65535) - PHP-FPM 的
pm.max_children不是越大越好:每个 child 平均吃 30–50MB 内存,200 个就是 6–10GB;得先看free -h和php-fpm -t是否语法通过
宝塔里怎么安全改 PHP-FPM 的 pm 模式和子进程数?
宝塔 Web 界面改配置容易覆盖或漏 reload,必须进终端确认生效。PHP-FPM 在宝塔中实际配置文件路径是 /www/server/php/{版本号}/etc/php-fpm.d/www.conf,不是面板里“设置”页显示的那个伪配置。
- 优先用
static模式(而非dynamic):避免 fork 开销,适合稳定流量;pm.max_children设为内存允许的最大值,比如 16GB 内存服务器,保守设 120 - 必须显式设
pm.start_servers=pm.min_spare_servers=pm.max_spare_servers(三者相等),否则 dynamic 模式下子进程频繁启停,引发 TIME_WAIT 泛滥 - 加一行
request_terminate_timeout = 30s,防慢脚本占满进程;宝塔界面不暴露这项,必须手动加到www.conf末尾 - 改完执行
systemctl reload php-fpm-{版本号},再用ps aux | grep php-fpm看实际进程数是否匹配
Nginx 与 PHP-FPM 通信走 socket 还是 TCP?
本地通信选 Unix socket 更快、更省资源,但宝塔默认用 127.0.0.1:9000(TCP)。问题在于:TCP 有 TIME_WAIT、端口耗尽风险;socket 则依赖文件权限和路径长度限制。
- 改 socket 要两步:① 修改
www.conf中listen = /tmp/php-cgi-{版本号}.sock,并删掉listen.allowed_clients(socket 不需要);② 修改网站 Nginx 配置里的fastcgi_pass为unix:/tmp/php-cgi-{版本号}.sock - socket 文件权限必须是
www:www(宝塔默认运行用户组),且listen.owner/listen.group要对应设成www,否则 502 - 如果用 TCP,务必在
www.conf加listen.backlog = 65535,并在系统执行sysctl -w net.core.somaxconn=65535,否则队列溢出静默丢包
调完参数,怎么验证是不是真生效了?
别只看 top 或面板数字,要抓真实链路瓶颈。很多“调优后更卡”的情况,其实是数据库连接池打满、Redis 阻塞,或 PHP 里用了 sleep()、file_get_contents() 同步调外部接口。
立即学习“PHP免费学习笔记(深入)”;
- 用
ss -s看 socket 统计:如果tw(TIME_WAIT)超过 1 万,说明 TCP 连接释放慢,该切 socket 或调net.ipv4.tcp_tw_reuse - 用
php-fpm -m查当前模式,systemctl status php-fpm-{版本号}看是否 active(running),别信面板“已重启”提示 - 压测时开两个终端:一个跑
watch -n1 'ps aux | grep php-fpm | wc -l',另一个跑nginx -T 2>/dev/null | grep "worker_connections",对比数值是否对得上 - 最易忽略的一点:
open_basedir在宝塔里默认开启,如果代码里有跨目录 include,会静默失败并卡住进程——关掉它或精确配置路径



















