尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

502 Bad Gateway 排查全攻略:从 Nginx 到本地开发工具

502 Bad Gateway 排查全攻略:从 Nginx 到本地开发工具 开门见山说个事儿凡是跟后端接口、网关、反向代理打过交道的人几乎都见过502 Bad Gateway这行字。尤其是最近半年身边好几个同事在本地跑 AI 编程助手、调试工具的时候也频繁遇到unexpected status 502 bad gateway: unknown error, url: http://127.0.0.1:15721/v1/responses这种报错第一反应都是我代码是不是写崩了结果排查半天发现根因五花八门。这篇文章我就把自己这些年排查 502 的完整思路整理出来既有传统 Nginx 网关场景下的常见原因也有现在开发工具本地服务报 502 的新坑。我会把原理、排查步骤、实际案例、以及那些文档里不会写的细节一次讲清楚希望能帮你在下次遇到 502 的时候不再对着屏幕发懵。1. 502 到底是什么先搞懂网关这个概念1.1 从一个生活例子讲起你可以把 502 理解成中间人传话失败。想象一下你打电话给前台说要找技术部的小张前台答应帮你去叫结果过了一会儿前台回来告诉你小张那边没人接电话我也没办法。你听到的没人接电话这个结果就是 502。在 HTTP 协议里这个中间人就是网关Gateway或者反向代理最常见的就是 Nginx、Apache、HAProxy还有云厂商的负载均衡器。客户端请求先打到网关网关再把请求转发给后面的真实服务器也就是后端应用比如 Java 的 Spring Boot、Python 的 Gunicorn、Node.js 的 Express。如果后端服务器没有正常返回响应网关就会代替后端返回一个 502 给客户端。1.2 502 在协议层面的准确定义按照 RFC 7231 的定义502 Bad Gateway 表示网关或代理服务器从上游服务器收到了无效响应。这里有两个关键词上游服务器upstream和无效响应。什么算无效响应范围很广上游服务器根本没有启动TCP 连接直接被拒绝上游服务器接受连接后迟迟不返回任何数据直到网关超时上游服务器返回的响应格式错误比如 HTTP 头不完整上游服务器在处理请求时进程崩溃连接被重置上游服务器返回了非法的状态码或者响应体所以你要记住一件事502 是一个结果不是原因。它只是网关在告诉你我这边没有从后端拿到能用的东西真正的问题出在哪一层需要继续往下查。有一类特殊情况需要注意如果网关配置的上游地址本身解析不了或者连接被防火墙拦截网关也可能报 502而不是 504。很多人在这一步就被带偏了以为是后端代码的问题其实是网络层面的连接根本没建立起来。2. 传统 Web 架构里的 502最常见的那几个坑2.1 后端服务挂了或者压根没起来这是最朴素也最常见的原因。Nginx 配置里写了一个 upstream指向127.0.0.1:8080但当请求打过来的时候8080 端口上没有任何进程在监听。Nginx 尝试建立 TCP 连接内核直接返回Connection refused于是 Nginx 只能给你一个 502。我在实际项目中遇到过一种很典型的场景开发环境用 Docker Compose 起了一整套服务有一次同事改了 docker-compose.yml 里的端口映射把后端服务的映射端口从 8080 改成了 8081但是 Nginx 的 upstream 配置没同步改结果前端页面全部白屏接口统统 502。排查方式也直接# 先确认端口有没有进程在监听 netstat -tlnp | grep 8080 # 再确认进程本身活着 ps aux | grep java ps aux | grep gunicorn # 如果是 Docker看容器状态 docker ps -a | grep backend如果端口没监听说明服务没起来或者启动失败去查应用日志如果端口有监听但还是 502那就往下面几个方向查。2.2 超时时间设置得太短后端慢就被掐断这个坑非常隐蔽因为后端服务其实好好的只是处理请求的时间超过了网关设定的阈值。Nginx 里有三个关键的超时参数proxy_connect_timeout和后端建立 TCP 连接的超时时间默认 60 秒proxy_read_timeout从后端读取响应的超时时间默认 60 秒proxy_send_timeout向后端发送请求的超时时间默认 60 秒我遇到过最经典的一个案例某个报表导出功能需要查大量数据平时 10 秒以内能返回但到了月底数据量暴增查询耗时超过 60 秒。Nginx 在 60 秒时主动断开了连接前端就收到了 502。从后端日志来看SQL 还在执行代码也没报错整个系统看起来一切正常。这种问题的排查思路不是去该代码而是要分清服务慢和服务挂的区别。你可以用 curl 直接请求后端接口带上--max-time参数看看后端实际需要多久# 直接访问后端不走 Nginx curl -v --max-time 90 http://127.0.0.1:8080/api/export # 再走 Nginx 访问一遍 curl -v --max-time 90 http://your-domain/api/export如果直连后端能正常返回但通过 Nginx 就 502基本可以断定是超时配置的问题。调大proxy_read_timeout是一个解法但更根治的做法是优化接口性能或者把耗时任务改成异步处理不要让 HTTP 请求一直挂在那。2.3 端口、防火墙、DNS 解析这些看不见的墙有时候后端服务明明活着代码也没问题但 502 就是莫名出现。这时候你得考虑网络链路中间环节。我在云服务器上排查过一个非常头疼的问题Nginx 和后端服务都在同一台机器上upstream 指向的是内网 IP而不是 127.0.0.1。这个内网 IP 是本机绑定的一个私有地址结果云平台的安全组规则只放行了公网 IP 的访问导致 Nginx 转发到内网 IP 时被防火墙拦截连接直接超时报 502。还有一种情况和 DNS 有关。如果 upstream 配置的是域名而后端服务的域名解析突然失败Nginx 在启动时解析不到 IP也会导致 502。有一个容易忽略的细节是Nginx 在启动时解析 upstream 域名之后默认不会重新解析除非配置了resolver。也就是说即使后来 DNS 恢复了Nginx 可能还拿着旧的、已经失效的 IP 在转发。排查网络层的问题我一般这样操作# 检查上游域名解析是否正常 dig your-backend-domain short nslookup your-backend-domain # 测试到后端端口的连通性 telnet 192.168.1.10 8080 # 用 curl 模拟网关转发时的请求 curl -v http://192.168.1.10:8080/health这里我多说一句telnet 不通不一定是端口没监听也可能是防火墙把包丢了。如果有条件用tcpdump在目标机器上抓包看一下能区分是连接被拒绝还是连接没响应。3. 开发工具里的 502codex / workbuddy / vscode 这类新场景3.1 本地回环地址 127.0.0.1 的报错拆解最近一年越来越多开发工具内部会启动一个本地服务然后工具自身通过 HTTP 接口和这个本地服务通信。比如 AI 编程助手 codex、workbuddy以及很多 CLI 工具都会在本地监听一个随机端口。当你看到这样的报错unexpected status 502 bad gateway: unknown error, url: http://127.0.0.1:15721/v1/responses它说的是工具内部组件尝试访问本机 15721 端口上的服务结果这个服务返回了 502。注意这里的 URL 是http://127.0.0.1:15721不是外网地址这说明整条链路都在你自己的机器上。出现这种情况通常和你的代码没关系而是工具内部的本地网关出了问题。这个本地网关的作用是接收工具的请求再把请求转发给真正的处理模块可能是本地的推理进程也可能是远端 API。如果后面的处理模块没有就绪、超时、或者进程崩了本地网关就会返回 502。3.2 write EACCES 权限问题的排查热词里有一条workbuddy 502 write eacces这里的EACCES是操作系统的权限错误意思是没有权限写入。这个报错一般不是 502 本身的原因而是伴随 502 出现的底层错误。我自己的实践经验是这类工具通常需要在用户目录下创建临时文件、写缓存或者写日志。如果你是用sudo方式启动了某个工具或者用户目录的权限被改过导致当前用户对某个目录没有写权限工具内部的本地服务就会启动失败或者运行时崩溃表现出来就是 502。排查办法# 查看工具的用户目录权限 ls -ld ~/.workbuddy ~/.codex 2/dev/null # 查看相关目录的属主和权限 find ~ -maxdepth 2 -name *workbuddy* -o -name *codex* -exec ls -ld {} \; # 如果权限不对可以修复属主 sudo chown -R $(whoami) ~/.workbuddy ~/.codex 2/dev/null这里要特别提醒一点不要用 sudo 去跑这类开发工具。用 sudo 启动后工具创建的缓存文件属主是 root之后再用普通用户启动就会因为权限问题连写日志都写不了各种诡异报错都会冒出来。3.3 本地服务端口被占用或未启动再看另一条热词vscode http 502: {error: urlopen error [winerror 10061] 由于目标计算机积极拒绝无法连接。}WinError 10061在 Windows 上是典型的连接被拒绝错误翻译成人话就是你试图访问的 IP 和端口上根本没有程序在监听。VSCode 的某个扩展试图访问本地某个端口但这个端口上没有服务所以报了一个类 502的错误。还有一条热词提到了127.0.0.1:1572一个截断的端口。这类本地服务端口通常是由工具动态分配的每次启动可能都不一样。如果端口被其他程序占用工具自带的本地服务可能无法绑定到这个端口导致后续请求全部失败。排查思路# Windows 上查看端口占用 netstat -ano | findstr 15721 # Linux / macOS 上查看端口占用 lsof -i :15721 netstat -tlnp | grep 15721 # 尝试手动访问本地服务 curl -v http://127.0.0.1:15721/v1/responses如果端口上确实没有进程那说明工具内部的本地服务没起来。常见的原因包括Node.js 版本太低、缺少系统依赖、工具的安装文件不完整。这时候可以试试彻底退出工具、清除缓存目录、重启工具。听起来很基础但我见过很多人卡在这一步最后就是重启解决的。3.4 这类工具 502 的本质本地转发链路不管报错文案怎么变unexpected status 502 bad gateway: unknown error这种格式都有一个共同特征工具内部有一个请求转发层转发失败后统一包装成了 502。这个转发层可以是 CLI 工具内置的本地 HTTP 代理也可以是 VSCode 扩展的 Node.js 子进程。它的工作模型是你在界面上操作向工具发出指令工具把指令封装成 HTTP 请求发到本地端口比如127.0.0.1:15721本地端口的服务收到请求后可能需要调用本地的其他进程或者把请求转发到远端如果第 3 步失败本地服务返回一个错误给工具工具把这个错误统一显示成502 bad gateway所以当你看到这类报错时核心排查方向不是我写了什么代码而是工具内部链路里哪个环节出问题了。我的经验是先看工具的日志文件几乎所有主流工具都会在用户目录下保留运行日志日志里的 stack trace 往往比界面上的错误信息有用得多。4. 一套能落地的排错流程从现象到根因的 6 步4.1 第一步先区分谁在返回 502收到 502 之后第一件事不是去翻代码而是确认 502 是从哪一层返回的。方法很简单直接 curl 一下报错的那个地址看响应头里的Server字段。curl -I http://your-service/api/test如果Server字段是nginx那说明是 Nginx 返回的 502问题在 Nginx 和后端之间。如果Server字段是其他值比如uvicorn、gunicorn、openresty那说明是应用层或者应用前面的其他组件返回的。还有一种情况在某些开发工具里502 是工具自己包装的响应头未必标准。这时候就去看工具的输出日志。4.2 第二步看日志看日志还是看日志我排查 502 的时候90% 的时间都在看日志。重点看三类日志网关日志Nginx 的error.log、access.log往往记录了 upstream 返回的具体状态后端应用日志Java 的 catalina.out、Python 的 gunicorn 日志、Node.js 的 stdout/stderr系统日志journalctl -xe、dmesg | tail有些时候后端进程是被 OOM Killer 干掉的这时候应用日志里什么都没有只能在系统日志里看到痕迹Nginx 的 error log 有一个非常有用的细节当上游连接被拒绝时它会记录connect() failed (111: Connection refused) while connecting to upstream当上游超时时会记录upstream timed out。这两句话直接告诉你问题性质。4.3 第三步验证后端健康状况网关说它没从后端拿到有效响应那我们就直接验证后端到底行不行# 绕过网关直接请求后端 curl -v http://127.0.0.1:8080/healthcheck curl -v http://127.0.0.1:8080/api/test # 看响应时间 curl -w time_total: %{time_total}s\n -o /dev/null http://127.0.0.1:8080/api/test如果直连后端能正常返回说明后端本身没挂问题出在网关到后端的链路或者网关的配置上。如果直连后端也报错那直接查后端应用的日志和进程。4.4 第四步检查超时与资源限制这里有一组我常用的命令专门用来排查资源类问题# 查看系统文件描述符限制 ulimit -n # 查看当前进程的文件描述符使用情况 ls /proc/$(pgrep -f your-backend)/fd | wc -l # 查看内存使用 free -h # 查看是否发生过 OOM Kill dmesg | grep -i killed process文件描述符用尽是很常见的 502 隐性原因。后端进程的文件描述符达到了上限新的连接进来时无法创建 socket表现就是网关报 502。这种问题在日志里通常表现为Too many open files。4.5 第五步复现与最小化验证如果前面的步骤都没找到问题就需要尝试复现。我一般这样做缩小请求范围用一个最简单的请求比如一个不带参数的 GET去测如果也 502说明是通用性问题如果只有特定请求才 502说明和参数、数据有关。切换路径绕过网关直连后端、或者换一个网关节点看是否复现。查看是否偶发连续请求 100 次看失败比例。如果是偶发 502大概率是超时、连接池、或者资源竞争的问题。这个方法在排查那种时好时坏的 502 时特别有效。4.6 第六步常用排查命令速查整理一份我自己平时用的命令速查表分享给大家排查目标命令端口监听状态netstat -tlnp/lsof -i :port进程是否存活ps aux | grep name/pgrep -f name后端接口连通性curl -v http://127.0.0.1:port/api响应耗时curl -w time_total: %{time_total}s -o /dev/null URL网关错误日志tail -f /var/log/nginx/error.log后端日志tail -f /var/log/your-app/app.log系统调用跟踪strace -p pid -e tracenetwork抓包tcpdump -i any port 8080 -nn -w capture.pcap5. 常见问题速查表与避坑心得5.1 经典场景对照表我在下面的表里整理了几个高频场景你可以直接对照排查现象可能原因首选排查动作所有请求都 502后端端口无监听后端服务没启动或启动失败netstat -tlnp | grep 端口看应用日志偶发 502直连后端正常网关超时配置过短或连接池耗尽调大 proxy_read_timeout压测验证重启后 502过一会儿恢复后端启动慢网关健康检查失败配置更长的超时或健康检查重试机制部分路径 502其他正常该路径对应的后端节点故障检查 upstream 配置逐个节点测试开发工具报 502URL 是 127.0.0.1工具内部本地服务未启动或崩溃查看工具日志检查对应端口占用报错带 EACCES目录权限问题导致工具无法写缓存检查用户目录文件权限避免 sudo 启动Windows 上报 10061目标端口没有服务监听netstat -ano | findstr 端口检查服务状态5.2 关于超时参数我踩过的坑很多人在 Nginx 里只调了proxy_connect_timeout发现不管用。原因是后端服务接受连接很快但处理请求很慢这时候瓶颈在proxy_read_timeout而不是connect_timeout。我建议你在配置的时候把三个超时参数都显式写清楚不要依赖默认值。一个我常用的配置参考location /api/ { proxy_connect_timeout 5s; proxy_read_timeout 60s; proxy_send_timeout 60s; proxy_next_upstream error timeout http_502; }这里proxy_next_upstream也值得说一嘴。如果你的 upstream 配置了多个后端节点开启这个指令后Nginx 在遇到错误或者超时的时候会自动重试下一个节点。但注意proxy_next_upstream不会对 POST 请求默认开启重试因为重试可能导致重复提交。如果业务允许可以加上non_idempotent参数但要谨慎。5.3 一个绕了半天的真实案例我最后分享一个记忆深刻的案例。某次线上服务频繁报 502但后端的 QPS 并不高CPU、内存都正常。我看了 Nginx 错误日志发现大量no live upstreams while connecting to upstream。这句话的意思是upstream 里的所有节点都处在不可用状态。我检查了后端进程明明活着。后来才发现Nginx 的健康检查配置max_fails和fail_timeout把节点标记为失败了。原因是有一次后端发布发布过程中健康检查接口响应变慢连续几次超过了 Nginx 的失败阈值Nginx 就把节点临时移出了可用列表。从那之后我养成了一个习惯看 502 的时候先去把 Nginx 的 error.log 翻完再去看后端。很多看起来像是后端问题的情况实际上是网关对后端状态的判断机制导致的。5.4 最后的个人体会排查 502 这么多年我最大的感受是502 本身不是一个错误而是整个请求链路的一个信号。它告诉你链路上某个环节没有按预期工作但具体是哪一个只能靠日志和分层验证来定位。所以我给所有被 502 困扰的朋友一个建议不要慌不要急着改代码先问自己三个问题——502 是谁返回的后端是不是真的有问题网关到后端的链路是否通畅把这三个问题回答清楚大部分 502 都能在十分钟内定位到根因。剩下的那一小部分翻翻日志、看看资源也基本都能水落石出。
返回列表