Nginx 502 Bad Gateway 后端到底挂了没有

FreeGuideOnline 最新 2026-07-04

nginx error_log /var/log/nginx/error.log warn; # 或者 debug


进入日志目录查看最近502相关的错误:

```bash
tail -f /var/log/nginx/error.log | grep "502\|upstream"

对照下表快速解读:

日志关键字 最可能的原因 后端状态
connect() failed (111: Connection refused) 后端未监听端口 挂了 / 未启动
connect() failed (110: Connection timed out) 防火墙拦截或网络不通 可能网络问题,非进程问题
upstream timed out (110: Connection timed out) 后端处理超时 活但慢
upstream prematurely closed connection 后端进程崩溃或异常退出 不稳定
no live upstreams 所有后端服务器都被标记为不可用 全部挂了或健康检查失败
recv() failed (104: Connection reset by peer) 后端主动重置连接 活但不正常

后端是否存活:一套有效检查命令

不要仅凭 ps 看进程就下结论。按照以下顺序逐步确认后端真实状态。

检查端口监听状态

ss -tlnp | grep :9000

如果没有任何输出,服务确实未启动。PHP-FPM 一般监听9000端口,其他服务替换为对应端口。

手动模拟一次请求

绕过Nginx,直接向后端发起请求,观察是否能得到正常响应。

对于HTTP后端(如Gunicorn、Tomcat):

curl -v http://127.0.0.1:8080/health-check

对于FastCGI后端(如PHP-FPM):

cgi-fcgi -bind -connect 127.0.0.1:9000 /status

或使用更简单的脚本模拟:

echo -e "GET /index.php HTTP/1.1\r\nHost: localhost\r\n\r\n" | nc 127.0.0.1 9000

(注意:PHP-FPM 需要配合 SCRIPT_FILENAME 等参数构造完整的fastcgi请求包,可以用 cgi-fcgicurl --unix-socket

检查进程数量与状态

ps auxf | grep php-fpm

关注 php-fpm: pool www 子进程是否全部处于 S (睡眠)状态,如果大量处于 R (运行) 或 D (不可中断睡眠),说明进程繁忙。若 TIME 列累计CPU时间过大,可能存在死循环。

查看系统资源瓶颈

  • 文件描述符ulimit -n(进程级别)和 /proc/sys/fs/file-max(系统级)
  • 连接追踪cat /proc/sys/net/netfilter/nf_conntrack_count 是否接近 nf_conntrack_max
  • 内存/CPUtophtop 查看是否有 OOM Killer 记录 (dmesg | grep -i kill)

常见后端(以PHP-FPM为例)的502解决方案

1. 端口或socket配置错误
确认Nginx与PHP-FPM的通信方式一致。如果用unix socket,确保两边路径相同且权限正确:

fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;

Socket文件必须可读可写,通常赋权:listen.mode = 0660 并在同一个用户组。

2. PHP-FPM进程数不足
pm.max_children 设得太低,请求排队导致超时。适当增加,但需结合服务器内存:

pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35

同时增大 request_terminate_timeout 防止单个请求永久占用。

3. 请求超时时间不匹配
Nginx的 fastcgi_read_timeout 必须大于 PHP 的 max_execution_time,避免PHP还在执行,Nginx已断开连接。

4. 后端返回头过大或缓冲不足
如果后端返回大量数据或响应头,可能突破Nginx的 proxy_buffer_sizefastcgi_buffer_size,导致连接中断。调大缓冲:

fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;