最后更新:2026-10-29
适用场景:Nginx 反向代理 Spring Boot,接口偶发或持续返回 502/504

用户说“接口挂了”,浏览器里只有一个 502 或 504。这时最容易做的事是重启 Java 服务,或者把 Nginx 超时时间调大。但如果还不知道请求停在哪一层,这两步都可能只是在掩盖问题。

先分清状态码。502 表示网关从上游拿到了无效响应;504 表示网关没能及时从上游拿到响应。它们指向的是代理与上游之间的交互,不等于 Spring Boot 一定抛了异常。若前面还有 CDN、负载均衡,先确认到底是哪一层返回的错误。RFC 9110给出了两种状态码的定义。

第一步:固定一条失败请求

记下失败时刻、完整 URL、HTTP 方法、响应状态和请求 ID(如果已有)。用同一条请求去对 Nginx 访问日志、错误日志和应用日志,别拿“首页能打开”来证明出错接口也正常。

如果没有请求 ID,至少先用时间、路径和客户端地址缩小范围。必要时为代理访问日志补上这些字段,以及 $request_time、$upstream_addr、$upstream_status、$upstream_response_time。后两个字段可以帮助判断 Nginx 访问了哪个上游、上游花了多久;发生重试时可能出现多个值,不要只读第一个数字。Nginx 日志模块和上游模块说明了字段含义。

改日志格式属于线上配置变更,先在测试环境验证;生产环境要核对配置、执行 nginx -t,再按现有发布流程平滑重载。不要为了排查把请求头里的 Cookie、Authorization 原样写进日志。

第二步:看代理有没有连上应用

Nginx 错误日志里如果出现 connect() failed、connection refused,先看 upstream 指向的地址和端口、Java 进程是否存活,以及容器或服务发现是否把请求送到了旧实例。若是 upstream prematurely closed connection,再查应用是否在处理过程中退出、重启或主动断开连接。不要只凭 502 页面猜根因,错误日志里的具体信息更重要。

在代理所在机器或同一内网环境里,按实际协议直连应用端口做对照。这里只是示意,地址、端口和路径都要替换成自己的:

curl -i --max-time 10 'http://127.0.0.1:8080/api/orders/42'
curl -i --max-time 10 'https://example.com/api/orders/42'

第一条只适用于 Nginx 与应用在同一机器且应用监听本机端口的场景。分机或容器部署应从代理所在网络访问实际 upstream 地址,不要为了测试临时开放后端公网端口。两条请求还应尽量保持方法、路径、鉴权和必要请求头一致,否则对照没有意义。

直连也失败,先处理应用和它依赖的服务;直连正常、经过域名失败,再看 Nginx upstream、路径转发、TLS 或更前面的网关。若是路径问题,可接着看接口返回 404 的排查。

第三步:504 要看“等在了哪里”

504 通常需要把时间线拼起来:Nginx 何时收到请求、何时连到上游、上游何时开始响应、应用日志里做了什么。Nginx 的 proxy_read_timeout 控制的是两次读取操作之间的等待时间,不是整个响应的总耗时上限;仅凭一个“60 秒”不能证明所有超过 60 秒的请求都会被切断。Nginx proxy 模块有明确说明。

请求已经进入 Spring Boot 时,先看同一时间段的接口耗时、线程状态、数据库慢查询和外部 HTTP 调用。项目若已接入 Actuator/Micrometer,可参考 http.server.requests 等指标;没接入就先用现有日志,别为了看一条指标临时公开管理端点。Spring Boot 指标文档说明了 HTTP 请求指标。

如果活动数据库连接打满、等待连接的请求持续增加,问题可能是连接池被慢 SQL 或长事务拖住,见数据库连接池耗尽排查。如果应用日志里根本没有对应请求,就把注意力放回代理、路由和网络,不要在 Controller 里盲目加日志。

最后再决定改什么

观察到的现象优先检查
502,代理连不上上游进程、监听地址、端口、容器网络、upstream 配置
502,上游提前断开应用重启、崩溃、连接处理和错误日志
504,应用确实收到请求慢 SQL、外部调用、线程等待、连接池
直连正常,域名请求失败Nginx 路由、前置网关、协议及请求头差异

确实有合法的长耗时接口,可以在确认业务预期后调整超时;普通接口若因慢查询或资源耗尽而超时,先修根因。把超时从 60 秒改到 300 秒,往往只是让用户多等四分钟。

修复后,用原来的 URL、方法和请求头复测,并观察一段时间的 5xx 数量与耗时。一次 curl 返回 200,只能说明那一次成功,不能证明偶发故障已消失。

参考资料

RFC 9110:502 与 504 定义
Nginx:Proxy 模块
Nginx:上游模块
Nginx:日志模块
Spring Boot 3.5:Metrics

更新记录

2026-10-29:创建文章,整理 502/504 的分层排查顺序。