502和504是Nginx反向代理时上游失败的两类表现:502因后端返回无效响应,504因后端超时无响应;需结合主动与被动健康检查(如health_check+max_fails/fail_timeout)并配置proxy_next_upstream识别502/504以实现自动故障隔离。

502 和 504 都是 Nginx 作为反向代理时向上游“求助失败”的表现,但原因不同:502 是后端返回了无效响应(比如进程崩溃、空响应、协议错乱),504 是后端迟迟不给响应(比如卡在数据库锁、GC 停顿、线程池满)。单靠日志盯错误码只能定位现象,真正要让故障自动收敛,必须让 Nginx 主动识别并隔离问题节点——这离不开健康检查与负载策略的配合。
明确健康检查类型:主动 + 被动缺一不可
主动健康检查(health_check)由 Nginx 定期发探测请求,判断节点是否存活;被动健康检查(max_fails/fail_timeout)则从真实业务请求中积累失败信号。两者协同才能覆盖全场景:
- 只配主动检查:探测路径轻量(如
/health),但若后端部分接口卡死而健康接口仍通,就会漏判 - 只靠被动检查:需等真实请求失败多次才摘除,期间用户持续遭遇 502/504
- 推荐组合:启用主动检查(间隔 5s、失败 2 次即标记为不健康),同时为每个 upstream server 设置
max_fails=2 fail_timeout=30s,确保探测失败和业务失败都能触发隔离
让 502/504 成为被动剔除的有效依据
默认情况下,Nginx 不会因上游返回 502 或 504 就认为节点异常。必须显式开启对应判定:
- 在 upstream 块中为每个 server 行添加
max_fails=3 fail_timeout=30s - 在 location 或 http 块中配置:
proxy_next_upstream error timeout http_502 http_504; - 这样,当某次请求因 502 或 504 被重试到其他节点后,原节点会记一次失败;连续达到
max_fails次,就被踢出服务池 30 秒
验证健康检查是否真生效
配置完别急着上线,用三步快速验证:
- 查 Nginx 状态页(需编译含
ngx_http_stub_status_module)或运行nginx -T | grep -A 10 "upstream",确认 health_check 指令已载入且参数无误 - 手动模拟故障:临时停掉一个后端服务,观察 Nginx error.log 是否出现类似
upstream server temporarily disabled的日志 - 查连接日志:开启
log_format记录$upstream_addr和$upstream_status,看 502/504 请求是否不再打向已被标记为 down 的节点
避免健康检查本身成为瓶颈
健康检查虽小,配置不当反而引发新问题:
- 探测路径不能走重逻辑,例如不要用
/api/users,而要用专用轻量接口如/health?ready,响应体控制在 1KB 内 - 避免高频探测压垮后端,
interval=5s对多数服务足够;若后端较脆弱,可延长至 10s 并调低fails阈值 - 注意
uri必须返回 HTTP 200,且不能重定向(302)或返回 5xx,否则会被视作失败


















