502 Bad Gateway 这个报错,但凡自己搭过网站或者折腾过服务器的人,迟早都会撞上。浏览器上就一行白底黑字,冷冰冰的,但背后的原因五花八门。简单说,它就是网关或者代理服务器从上游服务器收到了一个无效响应。什么叫无效响应?可能是上游直接没反应,可能是回应了一堆乱码,也可能是连接被掐断了。反正网关觉得“你给我的东西我没法用”,于是甩给用户一个502。
最常见的场景是 Nginx 做反向代理,后面跑着 PHP-FPM 或者 Node.js。用户请求过来,Nginx 把请求转给后端,后端如果挂了、卡死了、或者处理超时了,Nginx 等不到正常回应,就返回502。所以502本质上不是 Nginx 自己的错,它是个传话的角色,后端服务出问题,它只能告诉用户那边服务异常。

碰到502,第一步别急着重启服务器,先看日志。Nginx 的 error log 通常能直接告诉你问题在哪。比如 connect() failed (111: Connection refused) while connecting to upstream,这意思是后端根本没在监听那个端口,可能进程挂了,或者端口配错了。如果是 upstream timed out,那就是后端活着但处理太慢,超过了 Nginx 的等待时间。还有 no live upstreams,说明所有后端节点都被标记为不可用了。日志里这几行字比任何猜测都管用。
后端进程为什么会挂?原因太多了。PHP-FPM 进程池被打满是最常见的,尤其在小内存 VPS 上,几个并发请求就能把 pm.max_children 撑爆,新请求进不来,Nginx 那边就等超时。这时候去 ps aux 看一眼,如果一堆 php-fpm 进程都处于 D 状态或者 CPU 跑满,基本就是它了。临时办法是重启 php-fpm,但根治得调进程池参数,或者加内存。Node.js 的话,可能是代码里有个未捕获的异常直接把进程崩了,用 pm2 或者 systemd 拉起来的话会自动重启,但重启那一瞬间的请求就会收到502。
还有一种情况是后端没挂,但 Nginx 和后端之间的连接配置有问题。比如 Nginx 里 proxy_pass 指向的端口跟后端实际监听的不一致,或者后端只监听了 127.0.0.1,而 Nginx 在另一个容器里,根本连不上。Docker 环境下这种情况很多,容器网络没配好,Nginx 容器访问不到应用容器,报错就是 connection refused。检查一下 proxy_pass 的地址是不是容器名或者正确的内网 IP,端口有没有映射对。
超时设置也值得看一眼。Nginx 默认的 proxy_read_timeout 是60秒,如果后端处理一个请求要跑两分钟,那60秒一到 Nginx 就断开连接返回502。有些导出报表或者跑批处理的接口就容易触发这个。解决办法是在 location 块里把这个值调大,比如 proxy_read_timeout 300s;,同时后端的超时也要相应调整,别只改一边。
如果网站用了 CDN,502 可能压根不是你服务器的问题。CDN 节点回源的时候连不上你的源站,它就会给用户返回502。这时候得去 CDN 控制台看回源日志,确认是源站挂了还是 CDN 到源站的链路有问题。有时候源站防火墙把 CDN 节点的 IP 给拦了,也会造成回源失败。把 CDN 的回源 IP 段加进白名单通常能解决。
排查顺序其实可以固定下来:先看 Nginx error log,确定是连接拒绝、超时还是无可用上游。连接拒绝就去查后端进程和端口,超时就调参数或者优化后端性能,无可用上游就检查健康检查配置。如果日志里啥都没有,那就去看后端自己的日志,PHP 的 error log、Node 的 pm2 log、或者系统日志 journalctl -u 服务名,总有一个地方会留下线索。
临时救急的话,重启确实能顶一阵。systemctl restart nginx 和 systemctl restart php-fpm 轮流执行,很多时候网站就恢复了。但如果不找到根因,过一阵还会再犯。尤其是流量稍微上来就502的,八成是资源不够或者配置不合理,重启只是把问题往后推。
最后提一个容易被忽略的点:502 不一定全是坏事。有时候后端在部署新版本,重启过程中短暂出现502是正常的,等进程起来就好了。但如果持续502超过几分钟,那就别等了,按上面的路子排查。网站报错不可怕,可怕的是不知道去哪找原因。502至少给了你明确线索,问题出在网关和上游之间。