502 Bad Gateway 全链路排查指南:六种成因与实战定位方法

发布时间:2026/10/23 9:41:29
502 Bad Gateway 全链路排查指南:六种成因与实战定位方法 502 这个状态码做运维和开发的人几乎都见过。页面一打开白屏中间一行冷冰冰的 “502 Bad Gateway”用户截图发过来第一句话往往是“网站挂了”。但真到服务器上一看后端进程活得好好的CPU 不高内存也够日志里还找不到明显异常。这种时候最容易犯的错就是重启服务了事——重启完确实好了过两天又冒出来反复几次之后你才发现根子根本不在你以为的地方。这篇内容就是围绕 502 报错这件事展开的。它是什么、由谁返回、六种常见成因分别怎么排查、每一步该看哪个日志、哪些参数值得调、哪些坑我踩过。适合后端开发、运维、SRE也适合刚接手线上服务、被 502 搞得一头雾水的同学。我不打算给你一堆“检查网络、重启服务”的空话而是把每一种成因的排查链路拆开让你下次看到 502 时能按图索骥地定位到具体是哪一层出了问题。1. 先把 502 的返回链路搞清楚不然排查全是瞎猜很多人排查 502 效率低根本原因是对“这个 502 是谁返回的”没有概念。502 的全称是 Bad Gateway直译是“坏网关”。它不是一个“服务器内部错误”那是 500也不是“服务不可用”那是 503它的语义非常明确作为网关或代理的那一方从上游服务器收到了无效响应。这句话拆开看有三个角色客户端、网关/代理、上游服务器。客户端请求先到网关可能是 Nginx、HAProxy、API 网关、云负载均衡网关再把请求转发给上游可能是应用进程、另一个服务、容器里的 Pod。502 是网关生成并返回给客户端的意思是“我联系上游了但上游给我的东西我看不懂或者压根没联系上”。1.1 谁在替上游“背锅”理解这一点极其关键。你在浏览器里看到的 502来源可能是Nginx 作为反向代理连不上后端的应用端口云厂商的负载均衡器健康检查失败后把请求打到了不健康节点容器编排里的 Ingress 控制器后端 Service 没有可用 Endpoint应用前面的 API 网关上游超时或返回了非法响应。这几种情况的排查入口完全不同。所以第一步永远是确认这个 502 的响应头里Server 字段是谁。用 curl 看一眼curl -I https://your-domain.com/some-path响应里如果有Server: nginx那基本就是 Nginx 层返回的如果是云厂商的标识就去查负载均衡的健康检查如果是某个网关框架的标识就去查那个网关的日志。别小看这一步我见过太多人对着应用日志翻了半天结果 502 是前面那层负载均衡发出来的应用根本没收到请求。1.2 网关和上游之间的“对话”到底发生了什么网关转发请求给上游本质是一次 TCP 连接加一次 HTTP 交互。502 出现的时机通常落在这几个环节建立连接阶段网关连不上上游的 IP:Port比如上游进程没起来、端口没监听、防火墙拦了、安全组没放行。发送请求阶段连接建立了但请求发到一半连接被重置。等待响应阶段请求发出去了上游迟迟不返回超过网关配置的超时时间网关主动断开并返回 502有些配置下是 504取决于具体实现。解析响应阶段上游返回了内容但不符合 HTTP 协议比如响应头格式错误、提前关闭连接、返回了空响应。这四类环节对应的是完全不同的排查方向。连接阶段的问题看网络和进程状态等待阶段的问题看超时配置和后端处理耗时解析阶段的问题看后端代码有没有写出畸形响应。把这条链路记在脑子里后面六种排查方法就有了归属。1.3 为什么不能一上来就重启重启能“解决”502是因为它把上游进程重新拉起来了连接自然恢复。但它掩盖了真正的问题可能是内存泄漏导致进程被系统杀掉可能是连接池耗尽可能是某个慢查询把工作线程全占满了。重启只是把定时炸弹的倒计时重置了一遍。我的习惯是先取证再动手。进程状态、连接数、最近的错误日志、当时的系统负载这些信息在重启之后就没了。养成先抓现场的习惯比会重启重要得多。2. 第一种上游进程根本没在监听连接直接被拒这是最“干脆”的一种 502。网关去连上游端口对方直接回一个 RST连接建立失败网关立刻返回 502。这种问题的特点是报错来得非常快几乎是瞬间返回不会让你等超时。2.1 怎么确认是连接被拒在网关所在的机器上直接用手上的工具去连上游端口# 假设上游是 127.0.0.1:8080 curl -v http://127.0.0.1:8080/health # 或者用 nc 探测端口 nc -zv 127.0.0.1 8080如果返回Connection refused那基本坐实了目标端口上没有进程在监听。这时候去看 Nginx 的 error log通常会有类似这样的记录connect() failed (111: Connection refused) while connecting to upstream111就是 ECONNREFUSED连接被拒。看到这个错误码方向就很明确了。2.2 进程活着但端口没监听是怎么回事有时候ps能看到进程在但端口就是连不上。常见原因有几个进程启动到一半卡住了比如初始化时连数据库超时主进程还在但监听 socket 还没创建。这种情况看进程的启动日志通常停在某个初始化步骤。监听地址不对进程监听的是127.0.0.1:8080而网关配的上游是192.168.x.x:8080。本机回环地址外部访问不到自然连不上。用ss -lntp看清楚监听的是哪个地址。端口被别的进程占了进程启动时绑定端口失败但错误被吞掉了进程以某种降级模式继续跑着。ss -lntp | grep 8080能看到实际占用者是谁。容器里监听的是 localhost容器内应用监听127.0.0.1容器外或同 Pod 的其他容器访问不到。这是容器化部署里非常高频的坑应用要监听0.0.0.0才能被外部访问。# 看清楚监听地址、端口、对应进程 ss -lntp # 或者 netstat -lntp2.3 一个容易被忽略的细节IPv6 与 IPv4有次排查一个“间歇性 502”最后发现是上游同时监听了 IPv4 和 IPv6但网关解析域名时优先走了 IPv6而 IPv6 那条链路有问题。表现就是时好时坏。用curl -4和curl -6分别测一下能快速区分。Nginx 里如果上游写的是域名解析行为受resolver配置影响必要时直接写死 IP 或者明确指定地址族。提示确认连接被拒之后别急着改配置。先搞清楚进程为什么没起来——是崩溃了、被 OOM 杀了、还是启动脚本本身有问题。dmesg -T | grep -i kill能看到有没有被系统杀掉的记录。3. 第二种连上了但等不到响应超时才是真凶比连接被拒更隐蔽的是超时。网关成功连上了上游请求也发出去了但上游迟迟不返回网关等到超过自己配置的时间主动断开连接并返回 502。这种 502 的特点是要等一段时间才出现用户感知就是“页面转圈很久然后报错”。3.1 超时到底是谁的超时这里有个特别容易混淆的点链路上有好几层超时任何一层先到点都会表现为 502 或 504。超时层级典型配置项作用网关连接上游Nginxproxy_connect_timeout建立 TCP 连接的最长等待网关等待响应Nginxproxy_read_timeout两次读操作之间的最长间隔网关发送请求Nginxproxy_send_timeout两次写操作之间的最长间隔上游应用自身框架的请求超时、数据库查询超时应用内部处理的最长耗时云负载均衡空闲超时、响应超时负载均衡层的等待上限排查时要先确认是哪一层先超时。看网关的 error log超时通常记录为upstream timed out (110: Connection timed out) while reading response header from upstream。看到while reading response header说明连接建立了、请求发了但响应头迟迟没回来问题在上游处理慢。3.2 上游为什么慢从线程池到慢查询上游处理慢的原因按我遇到的频率排个序数据库慢查询一条没走索引的 SQL平时数据量小没事数据涨上来之后单次查询几秒甚至几十秒。应用的工作线程全被这条查询占着后续请求排队最终网关超时。下游依赖拖慢应用调用了另一个服务那个服务响应慢应用跟着慢。这种要顺着调用链往下查。线程池/连接池耗尽应用配置的线程数或连接数不够高并发下请求排队等待等待时间超过网关超时。GC 停顿某些运行时环境下长时间 GC 会让进程“卡住”几秒期间不处理任何请求。锁竞争某个全局锁被长时间持有其他请求全在等锁。定位这类问题光看网关日志不够得看上游应用的日志和监控。重点看请求耗时分布是普遍慢还是个别慢。普遍慢通常是资源瓶颈或下游拖累个别慢往往是特定请求触发了慢查询或锁。3.3 超时参数怎么调才不背锅很多人一遇到超时就把proxy_read_timeout调大从 60 秒调到 300 秒。这治标不治本而且有副作用上游真的挂了的时候网关要等更久才返回错误用户等得更久连接资源占用更久。我的原则是超时参数应该匹配业务的实际处理时间而不是用来掩盖慢。先通过监控拿到接口的 P99 耗时把网关超时设成略大于 P99 的值比如 P99 是 2 秒超时设 5 秒。如果发现大量请求逼近这个值说明该优化上游了而不是继续调大超时。location /api/ { proxy_pass http://backend; proxy_connect_timeout 3s; proxy_send_timeout 10s; proxy_read_timeout 10s; }注意proxy_read_timeout指的是两次读操作之间的间隔不是整个请求的总时长。如果上游是流式返回每隔几秒吐一点数据这个超时不会触发。理解这一点能避免很多误判。4. 第三种上游进程崩溃或被杀连接中途断开这种 502 的表现介于前两者之间连接建立过请求可能也处理了一部分但上游进程突然没了连接被重置。网关收到的是连接重置或提前关闭返回 502。日志里常见的是upstream prematurely closed connection while reading response header from upstream。4.1 进程为什么会突然消失进程非正常退出的原因排查时按这个顺序看被 OOM Killer 干掉内存用超了系统内核直接杀进程。dmesg -T里能看到Out of memory: Killed process的记录。这是生产环境里非常常见的一种尤其是 Java、Node 这类吃内存的应用。段错误崩溃底层库或原生扩展出问题进程直接 segfault。看系统日志或 core dump。被部署系统重启滚动发布、健康检查失败触发的重启进程在请求处理中途被替换。主动退出代码里有process.exit()之类的逻辑遇到某种条件就退出了。4.2 从日志时间线还原崩溃现场排查这类问题最有价值的是时间线对齐。把网关报 502 的时间点和上游进程的日志、系统日志、监控指标对齐看崩溃前发生了什么。具体做法拿到 502 发生的精确时间网关日志里有然后去查上游应用日志在这个时间点前后有没有异常堆栈、有没有正常关闭的记录系统日志dmesg、/var/log/messages有没有 OOM 或硬件相关记录监控上这个时间点的内存、CPU、连接数曲线。我遇到过一次502 每隔几小时出现一次最后对齐时间线发现是内存缓慢上涨涨到阈值被 OOM 杀掉重启后重新上涨循环往复。根因是代码里有个缓存没有淘汰策略只增不减。这种问题不抓时间线根本看不出来。4.3 内存问题的排查抓手如果怀疑是内存导致的崩溃几个实用手段# 看进程内存占用 ps aux --sort-%mem | head # 看系统 OOM 记录 dmesg -T | grep -i out of memory # 看进程被杀的信号9 通常是 SIGKILL对于长时间运行的服务建议加上内存监控和告警在接近阈值时提前介入而不是等它被杀。另外容器环境要特别注意容器的内存 limit超过 limit 容器会被杀掉表现和 OOM 类似但日志在容器运行时那边。5. 第四种响应格式非法网关“看不懂”上游的回复这一类 502 最让人困惑因为上游明明返回了内容进程也没崩但网关就是不认。原因是上游返回的响应不符合 HTTP 协议规范网关解析失败只能返回 502。5.1 哪些“畸形响应”会触发 502常见的几种响应头格式错误比如 header 里出现了非法字符、缺少必要的换行、header 名带了空格。Content-Length 与实际内容不符声明了 100 字节实际只发了 50 字节就关闭连接网关等不到剩余内容。在响应头之前输出了内容应用代码里不小心print了调试信息导致响应体出现在响应头之前协议直接乱掉。HTTP 版本或状态行异常上游返回了网关无法识别的状态行。分块传输编码错误chunked 编码的块大小格式不对。这类问题的排查关键是抓包看原始响应。用curl -v或者抓包工具看上游到底返回了什么字节流。很多时候一看原始响应就明白了比如响应头前面多了几行调试输出。5.2 一个真实场景调试输出污染了响应我见过一个案例某接口偶发 502频率不高但一直存在。最后抓包发现某个分支的代码里有一行调试用的打印语句在特定条件下会往标准输出写内容而标准输出被重定向到了响应流里。大部分请求走不到那个分支所以只是偶发。这种问题看应用日志看不出来因为打印的内容本身不报错只有抓原始响应才能发现。排查这类问题的思路是在网关侧记录上游返回的原始响应。Nginx 可以通过error_log的 debug 级别看到部分信息或者在上游应用侧加一个中间件把响应头和响应体的前若干字节记下来。定位到具体接口后再去看那个接口的代码。5.3 上游返回空响应也算还有一种情况上游接受了连接但什么都没返回就关闭了。网关等响应头等不到连接就断了同样报 502。这可能是应用在处理请求时抛了未捕获的异常进程没崩但连接被框架关闭了也可能是某个中间件直接close了连接。看应用日志里有没有未处理异常的记录通常能找到线索。6. 第五种连接池与并发瓶颈请求在网关侧就排不上队这一类 502 容易被忽略因为它不是上游“坏了”而是上游忙不过来。网关到上游的连接数是有上限的当并发请求超过这个上限新请求要么排队要么直接被拒。6.1 连接数打满的典型表现Nginx 作为网关时到上游的连接管理有几个关键点upstream块里默认没有限制单个上游的连接数但keepalive连接池有大小限制如果没开 keepalive每个请求都要新建连接高并发下端口耗尽或 TIME_WAIT 堆积开了 keepalive 但池子太小连接复用不够同样会频繁建连。表现上502 会集中在流量高峰出现低峰期正常。看网关的active连接数、上游的并发连接数能看出端倪。upstream backend { server 127.0.0.1:8080; keepalive 64; # 保持的连接数 keepalive_requests 1000; keepalive_timeout 60s; } location / { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Connection ; }注意proxy_http_version 1.1和清空Connection头这两行是启用 keepalive 的必要条件漏了的话连接池形同虚设。6.2 上游的连接队列被打满上游应用本身也有连接队列。以常见的应用服务器为例监听 socket 有一个 backlog 队列队列满了之后新的连接请求会被拒绝或丢弃。这时候网关建连就会失败表现为 502。# 看监听队列的溢出统计 ss -lnt # Recv-Q 是当前排队数Send-Q 是 backlog 上限 # 如果 Recv-Q 经常接近 Send-Q说明队列快满了调大 backlog 能缓解但根本还是要提升上游的处理能力或者做限流。队列满说明请求进来的速度超过了处理速度光调大队列只是把问题往后推。6.3 限流和降级才是长久之计连接池和队列都是缓冲缓冲再大也有上限。真正稳的做法是在网关层做限流超过阈值的请求直接快速失败返回 429 或 503而不是让它们堆在队列里最终变成 502。快速失败对用户来说至少是明确的堆在队列里最后超时反而体验更差。限流的阈值怎么定看上游在压测下的最大吞吐取一个留有余量的值。比如压测显示单机能扛 2000 QPS限流就设在 1500 左右给突发留空间又不至于把上游压垮。7. 第六种健康检查与负载均衡配置把请求打到了坏节点在有多实例、前面挂负载均衡的架构里502 还有一个高频来源负载均衡把请求转发到了一个实际不可用的节点。这通常和健康检查配置有关。7.1 健康检查为什么没拦住坏节点健康检查的逻辑是负载均衡定期探测后端节点探测失败就把节点摘除不再转发流量。但以下几种情况会让坏节点“漏网”检查间隔太长节点挂了但距离下次检查还有 30 秒这 30 秒内的请求全打到坏节点上全是 502。检查路径不具代表性健康检查探的是/health这个接口只返回 200 不检查依赖而实际业务接口因为数据库连不上已经废了。健康检查通过业务请求失败。失败阈值太高要连续失败 5 次才摘除每次间隔 10 秒那就是 50 秒的窗口期。被动检查缺失只有主动探测没有根据实际请求的失败率做被动摘除。7.2 主动检查与被动检查要配合主动健康检查负责发现“节点整体不可用”被动检查也叫异常检测负责发现“节点在处理实际请求时出错”。两者配合才能快速摘除坏节点。以常见的负载均衡配置为例思路是主动检查间隔缩短到 5 秒以内失败 2 到 3 次即摘除开启被动检查连续若干个 5xx 响应就把节点临时摘除一段时间健康检查接口要真实反映依赖状态数据库、缓存连不上就返回失败。提示健康检查接口不要做得太重别在里面跑复杂查询。它会被高频调用太重反而增加负担。检查关键依赖的连通性即可。7.3 优雅下线别让请求打到正在退出的节点滚动发布时节点正在退出但还没完全停止此时如果负载均衡还在往它转发请求就会 502。解决办法是优雅下线节点收到停止信号后先从负载均衡摘除等待一段时间让存量请求处理完再真正退出。这个“等待一段时间”要大于负载均衡的健康检查摘除时间。比如健康检查 5 秒一次、失败 2 次摘除那节点至少要等 10 秒以上再停服务。很多发布脚本里没做这个等待导致每次发布都有一小段 502用户感知就是“一发版就抖一下”。8. 排查 502 的通用动作清单与几个血泪教训前面六种成因讲完最后给一套可以直接照着做的动作清单。这套顺序是我自己排查时用的从快到慢、从外到内能覆盖大部分场景。8.1 从响应头到日志的固定动作curl -I看 502 是谁返回的确认网关层。看网关 error log拿到具体的错误描述和错误码111 连接被拒、110 超时、连接重置等。在网关机器上直接探测上游端口区分“连不上”还是“连上了但慢”。看上游进程状态、监听地址、内存占用。对齐时间线看崩溃或超时时刻的系统日志和监控。必要时抓原始响应排查畸形响应。这套动作的价值在于每一步都在缩小范围而不是东一榔头西一棒子。错误码是最快的分诊依据111 和 110 指向完全不同的方向先分清再深入。8.2 几个我踩过的坑坑一只看应用日志不看网关日志。有次 502 查了半天应用最后发现是网关的proxy_read_timeout设得太短应用其实 3 秒就返回了网关 2 秒就断了。网关日志里明明白白写着超时我却在应用里找了一下午。坑二把 502 和 504 混为一谈。两者都和上游有关但 504 明确是超时502 的范围更广。有些网关实现里超时也返回 502导致误判。看日志里的具体错误描述比看状态码更可靠。坑三忽略 TIME_WAIT 堆积。短连接高并发场景下大量 TIME_WAIT 会耗尽可用端口新建连接失败表现为 502。ss -s看 TIME_WAIT 数量如果几万甚至更多就要考虑开 keepalive 或者调内核参数了。坑四健康检查接口返回 200 但依赖已挂。这个前面提过健康检查要检查真实依赖否则就是个摆设。8.3 预防比排查更值钱502 排查得再熟也不如让它少发生。几个预防性的做法网关和上游都配好合理的超时并且和业务耗时匹配上游加内存监控和告警别等 OOM负载均衡的主动检查和被动检查都开起来发布流程里加优雅下线等存量请求处理完再停关键接口的耗时做监控P99 逼近超时阈值时提前优化。我个人在实际操作中的体会是502 本身不可怕可怕的是没有现场。只要日志、监控、时间线这三样东西齐全绝大多数 502 都能在半小时内定位到根因。真正耗时的往往不是排查而是现场已经被重启破坏了只能等它下次复现。所以再强调一遍先取证再动手。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询