Nginx 反向代理导致 504 网关超时,怎么解决?

Nginx 反代 504 Gateway Timeout 排查:proxy_read_timeout 等超时参数调优、上游应用慢在哪、长任务异步化、按 URI 分级超时配置与 FAQ。

最佳实践
Nginx 反向代理导致 504 网关超时,怎么解决?封面

504 表示网关等待上游超时,可能在连接或响应阶段;先用日志确认由 Nginx 还是其他网关返回。 两条处置线并行:调大 Nginx 的代理超时参数治标;查清上游为什么慢治本。

治标:调大超时参数

location / {
    proxy_pass http://backend;

    proxy_connect_timeout 60s;    # 连上游的建立连接超时(默认 60s,一般够用)
    proxy_send_timeout    120s;   # 往上游写请求的超时
    proxy_read_timeout    120s;   # 等上游响应的超时(504 多半栽在这)
}

这组 proxy 指令适用于 HTTP 代理;PHP-FPM 等 FastCGI 上游应使用对应的 fastcgi_*_timeout 指令。

三个参数的分工:

指令 管哪段 默认值
proxy_connect_timeout TCP 连接上游的握手 60s
proxy_send_timeout 两次写操作之间的间隔 60s
proxy_read_timeout 两次读响应之间的间隔 60s

注意:read_timeout 是两次读到数据之间的间隔,不是整个响应的总时长——上游持续吐数据就不会触发。整个请求都很慢的"长任务",光调它不够。

治本:找出上游为什么慢

504 是超时症状,可能发生在建立上游连接或等待响应阶段,也可能涉及网络:

# 上游还活着吗?
curl -v http://backend-ip:port/health

# 上游日志:请求到了吗?处理多久?
tail -f /var/log/app/app.log

高频病因:慢查询拖住接口、上游线程/连接池耗尽、上游自己又在等更下游的服务、应用 GC 停顿。

先从同一条访问日志取出 URI、请求时间与上游耗时,再检查对应时间窗口的应用请求。若应用已接入观测云 APM,可在链路详情中查看已采集 Span 的耗时,并用相同 trace_id 找到关联日志。未埋点的 Nginx 或数据库不会仅因接入 APM 就补出完整调用段。

工程层面的正确解法

  • 长任务异步化:报表导出、批量处理这类秒级回不来的活儿,改成"提交任务→立即返回→轮询/Webhook 通知",别让人肉 HTTP 请求硬等。
  • 按 URI 分级超时:普通接口 30s,确实需要慢的接口单独 location 放宽,别全局调成 600s——那会掩盖真问题。
  • upstream 健康检查:开源版可使用被动失败检测;主动健康检查需核对 Nginx Plus 或所用模块的支持。重试还需考虑非幂等请求重复执行的风险。

常见问题(FAQ)

Q:调大 timeout 后变成 502 了?
A:可能是连接被拒绝、无效响应,或上游进程在等待期间退出、主动断连(比如应用自己的超时更短,先掐了)。查上游的超时配置(如 Gunicorn 的 --timeout、PHP 的 max_execution_time),全链路要对齐。

Q:有些请求要跑 5 分钟,把 read_timeout 设 300s 合理吗?
A:可以,但需按业务时限和全链路资源预算评估;它控制两次读取之间的空闲时间。长任务通常更适合异步任务加通知机制,确需同步时也要配置客户端和其他代理的超时。

Q:怎么区分 504 和 502?
A:504 = 上游连接或响应阶段超时,不能据此确认后端仍活着;502 可由连接拒绝、异常断开或无效响应引起。error.log 里的文案分别是 upstream timed out 和 upstream prematurely closed connection 等。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台