从 502 排查到 PHP-FPM 配置
502 Bad Gateway 的意思是「上游给我的响应不合法或没响应」。它不是一个错误,而是一类错误的统称,排查要按固定顺序走。
第一步:区分 502 和 504
- 502:上游连接失败或过早断开——FPM 挂了、socket 不通、worker 崩溃;
- 504:上游超时——请求还在跑,只是超过了
fastcgi_read_timeout。
504 优先查慢代码;502 才是本文的重点。
第二步:FPM 还活着吗
systemctl status php-fpm # 或 php8.2-fpm
ps aux | grep php-fpm | head # master + 若干 worker
ss -lntp | grep 9000 # TCP 模式监听
ss -lx | grep php # unix socket 模式
看错误日志的顺序:Web 服务器 error log(connect() failed / timeout)→ FPM log → PHP error log。三层日志会分别指向不同原因。
三个最常见的原因
1. socket 路径不一致
Web 服务器配置写 /run/php/php8.2-fpm.sock,FPM 实际监听 /tmp/php-cgi-82.sock。改配置重启后 502 立刻出现。核对两边的 listen 与 fastcgi_pass。
2. worker 耗尽
# FPM 状态页(需配置 pm.status_path)
curl -s localhost/fpm-status | head -8
# 关注 active processes 是否等于 total,listen queue 是否持续大于 0
worker 全忙时新请求排队,超过 backlog 就被拒。解法是调大 pm.max_children(注意内存)或优化慢请求。
3. worker 执行中被杀
PHP 脚本触发段错误、被 OOM killer 杀掉、或 max_requests 重启窗口撞上高峰。dmesg 里搜 oom-kill 和 segfault:
dmesg -T | grep -iE 'oom|kill' | tail
配置层面的防御
; 给慢请求留日志
request_slowlog_timeout = 3s
slowlog = /var/log/php-fpm/slow.log
; 让 backlog 扛住瞬时尖峰
listen.backlog = 511
Web 侧再配 fastcgi_read_timeout、合理的重试策略(只对幂等请求重试),502 的发生率会显著下降。
最后提醒:恢复服务之后别忘了复盘根因。「重启就好了」只解决这一分钟,不解决下一次。