搞定 Nginx 502 Bad Gateway:一篇面向“人类”的技术指南


兄弟,又看到这个熟悉的 “502 Bad Gateway” 了?别烦,这玩意儿十个开发者里九个都遇到过。它就像是服务器跟你开的一个“无情玩笑”,告诉你:“哥们儿,我后面的服务挂了,你自己看着办吧!”

不过别担心,今天咱们就把它扒个底朝天,让你以后再见到 502 能像见到老朋友一样,淡定地说一句:“哦,原来是你小子,看我怎么收拾你!”

这篇文章会用最“说人话”的方式,带你过一遍 502 错误的常见原因和解决方法,保证有代码、有解析、有案例,让你彻底告别求爷爷告奶奶的窘境。

502 Bad Gateway 到底是啥?

首先,咱得明白 502 到底是啥意思。简单说,Nginx 就像一个饭店的前台,负责接待顾客(用户请求)。当顾客点餐后,前台会把菜单递给后厨(比如 PHP-FPM、Tomcat 等应用服务器)。

如果后厨因为某些原因(比如厨师罢工、食材不够、或者厨房着火了)没法正常做菜,并且给了前台一个错误的信号,前台没法给顾客上菜,就会很尴尬地告诉顾客:“对不起,后厨出问题了!” 这个“后厨出问题了”,就是我们看到的 “502 Bad Gateway”。

所以,核心问题往往不在 Nginx 本身,而在 Nginx 后面的那个“后厨”

“破案”第一步:查看“案发现场”—— 日志

遇到 502,别瞎猜。第一时间去翻看 Nginx 和你后端服务(比如 PHP-FPM)的错误日志,这比啥都管用。

  • Nginx 错误日志:通常在 /var/log/nginx/error.log
  • PHP-FPM 错误日志:位置可能在 /var/log/php-fpm/www-error.log 或者类似的地方,具体看你的配置文件。

日志里的一行错误信息,往往就能直接告诉你问题出在哪。

常见“元凶”与“抓捕”方案

下面我们来看看几个最常见的导致 502 的“元凶”,以及如何将它们“绳之以法”。

元凶一:PHP-FPM 进程“罢工”或“人手不足”

这是最常见的原因之一。Nginx 把请求转给 PHP-FPM,结果发现 PHP-FPM 进程挂了,或者忙不过来了,Nginx 自然就只能返回 502 了。

场景分析

你的网站突然访问量飙升,或者某个 PHP 脚本执行效率低下,占用了大量资源,导致 PHP-FPM 进程池里的进程全被占满了。新的请求过来,没有空闲的进程来处理,排队等着等着就超时了。

解决方案

  1. 检查 PHP-FPM 状态
    确保 PHP-FPM 服务正在运行。

    ps aux | grep php-fpm
    # 或者
    systemctl status php-fpm

    如果没在运行,赶紧启动它。

  2. 增加 PHP-FPM 进程数
    打开你的 PHP-FPM 配置文件(通常在 /etc/php-fpm.d/www.conf 或类似路径),调整进程管理相关的参数。

    ; pm = dynamic # 进程管理方式,dynamic 表示动态
    pm.max_children = 50      ; 最多能创建多少个子进程
    pm.start_servers = 20     ; 启动时创建多少个
    pm.min_spare_servers = 10 ; 至少保留多少个空闲进程
    pm.max_spare_servers = 30 ; 最多保留多少个空闲进程
    pm.max_requests = 500     ; 每个子进程处理多少个请求后就重启,有助于释放内存

    pm.max_children 的值不是越大越好,需要根据你服务器的内存来定。一个经验法则是,先看看一个 PHP-FPM 进程大概吃多少内存(比如用 top 命令),然后用 (总内存 - 其他服务占用内存) / 单个进程内存 来估算一个合理的值。

案例:一个电商秒杀活动引发的“血案”

问题:小明负责的电商网站搞秒杀活动,活动一开始,网站立马 502。
排查:他查看 Nginx 错误日志,发现大量 (111: Connection refused) while connecting to upstream 错误。接着检查 PHP-FPM,发现进程活得好好的。最后查看 PHP-FPM 的慢日志,发现大量的请求都卡在一个库存查询的接口上。
分析:秒杀瞬间涌入大量请求,把 PHP-FPM 的 max_children 进程池打满了。后续的请求都被拒绝,导致 Nginx 连接不上 PHP-FPM。
解决

  1. 紧急情况下,临时调大了 pm.max_children 的值,并重启 PHP-FPM,网站恢复。
  2. 活动结束后,优化了那个慢查询的 SQL 语句,并给相关数据加上了缓存,从根本上解决了问题。

元凶二:Nginx 与后端服务的“沟通障碍”—— 缓冲区和超时

有时候,后端服务处理一个请求返回的数据量太大了,或者处理时间太长了,超出了 Nginx 的“耐心”和“接纳”范围,也会导致 502。

场景分析

你正在导出一个巨大的报表,PHP 脚本吭哧吭哧跑了半天,终于生成了一个巨大的响应头(比如包含了很多 Cookie 信息)。结果 Nginx 的缓冲区太小,装不下,直接就报错了。

解决方案

调整 Nginx 配置文件中与 FastCGI 或代理相关的缓冲区(buffer)和超时(timeout)参数。

对于 FastCGI (PHP-FPM):
在你的 Nginx 站点配置文件的 location ~ \.php$ 块中或者 http 块中,加入或调整以下参数:

http {
    # ... 其他配置 ...
    fastcgi_buffers 8 16k;
    fastcgi_buffer_size 32k;
    fastcgi_connect_timeout 300s;
    fastcgi_send_timeout 300s;
    fastcgi_read_timeout 300s;
}
  • fastcgi_buffersfastcgi_buffer_size:增大了 Nginx 用来缓存 FastCGI 响应的缓冲区大小。 如果你在日志里看到 “upstream sent too big header” 这样的错误,多半就是这里需要调大。
  • fastcgi_read_timeout:指定了 Nginx 等待 PHP-FPM 响应的超时时间。如果你的 PHP 脚本需要执行很长时间,就需要调大这个值。

对于反向代理 (Proxy):
如果你是把请求代理到另一个服务(如 Tomcat, Node.js),则需要调整 proxy_ 相关的参数:

location / {
# ... 其他配置 ...
proxy_buffers 8 16k;
proxy_buffer_size 32k;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}

原理和 FastCGI 的类似,只是指令前缀不同。

改完配置后,别忘了 nginx -t 测试一下语法,然后 systemctl reload nginx 重载配置。

元凶三:资源耗尽 —— 内存或磁盘空间不足

这也是一个容易被忽略但很致命的问题。如果服务器的内存被吃光了,或者磁盘满了,PHP-FPM 可能就无法正常工作,甚至被系统“干掉”。

解决方案

  1. 检查内存

    free -m

    看看 available 还有多少。如果所剩无几,就需要排查是哪个进程占用了过多内存。

  2. 检查磁盘空间

    df -h

    检查挂载点,特别是 //var 目录,确保有足够的空间。日志文件、临时文件和上传文件都可能把磁盘撑爆。

终极武器:开启 PHP-FPM 状态页

想实时了解你的 PHP-FPM “后厨”到底忙不忙?可以开启它的状态页,这对于线上问题排查非常有帮助。

  1. 修改 PHP-FPM Pool 配置
    还是那个 www.conf 文件,找到并取消下面这行的注释:

    pm.status_path = /fpm-status
  2. 配置 Nginx
    在你的 Nginx 站点配置里,增加一个 location 块:

    location /fpm-status {
        # 只允许本机访问,保证安全
        allow 127.0.0.1;
        deny all;
    
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_pass unix:/var/run/php/php-fpm.sock; # 或者你的 PHP-FPM 监听地址
    }
  3. 重载服务后访问
    重载 PHP-FPM 和 Nginx。然后在本机通过 curl http://127.0.0.1/fpm-status 就可以看到类似下面的信息:

    pool:                 www
    process manager:      dynamic
    start time:           12/Sep/2025:10:00:00 +0000
    start since:          3600
    accepted conn:        12345
    listen queue:         0
    max listen queue:     1
    listen queue len:     0
    idle processes:       15
    active processes:     5
    total processes:      20
    ...

    其中 active processes(活跃进程数)、idle processes(空闲进程数)和 listen queue(等待队列)是非常关键的指标,能帮你判断进程池是否够用。

总结

好了,兄弟,关于 Nginx 502 的那些事儿,咱们今天就聊到这。记住,遇到 502 别慌,它只是一个信号,真正的“罪犯”在后端。

排查思路回顾:

  1. 先看日志:Nginx error log 和 PHP-FPM error log 是你的“第一案发现场”。
  2. 检查后端服务状态:确保 PHP-FPM(或你的其他应用)还“活着”。
  3. 检查资源:内存、CPU、磁盘空间是否充足。
  4. 调整配置:合理配置 PHP-FPM 进程数和 Nginx 的超时、缓冲区参数。
  5. 优化代码:从根源上解决执行慢、耗资源大的问题。

希望这篇“说人话”的指南能帮你彻底搞定 502。下次再遇到它,你就可以胸有成竹地开始你的“破案”之旅了!


  目录