对于使用 Nginx 或 Apache 作为前端代理的个人站长来说,502 Bad Gateway 错误是噩梦般的存在。用户访问时出现这个错误,通常意味着前端代理(Nginx)无法从后端应用服务器(通常是 PHP-FPM 进程)那里获取到响应。
核心结论: 您的猜测很可能是正确的。在大多数情况下,如果您的网站在流量高峰期报 502,其主要原因就是 PHP-FPM 的子进程数量(即并发数)设置太低,导致所有进程都被占满,新请求无法得到处理,最终超时。
本文将指导您如何诊断问题,并安全地计算和调整 PHP-FPM 的并发数。
第一步:诊断——确认是否是资源耗尽
在贸然修改配置之前,我们必须确认 PHP-FPM 是否真的被耗尽了。我们需要关注两个关键点:Nginx 错误日志和系统内存。
1. 检查 Nginx 错误日志
如果日志中包含 “upstream prematurely closed connection” 或 “connect() failed (111: Connection refused) while connecting to upstream”,则明确指向 PHP-FPM 失败或无力响应。
tail -n 50 /var/log/nginx/error.log
2. 检查内存使用情况
PHP 进程是非常消耗内存的。如果并发数设置过高,导致系统内存耗尽(OOM,Out of Memory),Linux 内核会自动杀死 PHP-FPM 进程,这也会导致 502 错误。
free -m
如果 available 接近于零,或者您在系统日志(如 /var/log/messages 或 dmesg)中看到 OOM Killer 的信息,那么您面临的不是并发数太少,而是内存不足。
第二步:实操——计算与配置 PHP-FPM 并发数
假设您确认内存尚有盈余,那么下一步就是调整 PHP-FPM 的配置。
1. 计算单个 PHP 进程的平均内存占用
您需要找到一个正在运行的 PHP-FPM 子进程,并查看其内存占用 (RSS)。
ps --no-headers -o rss,cmd -C php-fpm | awk '{ sum+=$1 } END { print "平均进程大小 (MB):",(sum/NR/1024), "总进程数:", NR }'
假设结果显示单个 PHP 进程平均占用 80MB。
2. 计算 Max Children (最大子进程数)
安全的 pm.max_children 数量的计算公式是:
$$Max Children = \frac{可用于 PHP 的总内存}{单个 PHP 进程的平均内存占用}$$
如果您的 VPS 有 4GB (4096MB) 内存,并且您打算留出 512MB 给操作系统和数据库等服务,那么留给 PHP 的是 3584MB。
$$Max Children = \frac{3584 MB}{80 MB} \approx 44$$
因此,您应该将 pm.max_children 设置为 44 或略低,如 40。
3. 修改 PHP-FPM 配置文件
PHP-FPM 的配置文件通常位于 /etc/php-fpm.d/www.conf 或 /etc/php/版本号/fpm/pool.d/www.conf。
找到以下参数并进行调整:
; 通常建议使用 dynamic 或 ondemand
pm = dynamic
; 根据您的内存计算结果设置。这里使用我们计算出的40作为示例。
pm.max_children = 40
; 启动时创建的进程数。建议设置为 Max Children 的 10-25%。
pm.start_servers = 10
; 最小空闲子进程数。
pm.min_spare_servers = 5
; 最大空闲子进程数。
pm.max_spare_servers = 20
; 设置每个子进程在重新启动前服务的最大请求数,有助于防止内存泄漏。
pm.max_requests = 500
第三步:应用更改并监控
配置修改完成后,必须重启 PHP-FPM 服务使之生效。
# 根据系统版本可能不同,通常是以下命令之一
systemctl restart php-fpm
# 或
systemctl restart php7.4-fpm
重要提醒: 调整完成后,请在流量高峰期持续监控 free -m 的输出。如果内存仍然迅速耗尽,说明您已经达到了当前硬件的瓶颈,唯一的解决方案是升级 VPS 配置。
汤不热吧