问题根源在Nginx配置:proxy_next_upstream误将404/403等业务状态码判为后端故障,导致反复重试同一节点并高频上下线,形成死循环;需删除http_403/http_404,仅保留error timeout及5xx错误触发重试。

健康检查死循环不是 Nginx 自身“反复重试同一节点”,而是配置不当引发的探测行为与后端响应相互强化,最终导致节点在 up/down 之间高频震荡、流量持续中断或代理层反复重试——本质是状态判定逻辑冲突或网络/业务层反馈被误读。排查需聚焦“谁在触发、依据什么判定、反馈是否可信”三个层面。
看 proxy_next_upstream 是否误判业务错误为后端故障
被动检查最常见死循环诱因:把 4xx 响应(如 404、403)当作后端异常,而这些其实是正常业务返回。一旦某路径频繁返回 403,Nginx 就会不断标记该节点失败 → 触发重试 → 又打到同一节点 → 再 403 → 再失败……形成闭环。
- 检查 location 中是否写了
proxy_next_upstream http_403或http_404;必须删掉,只保留error timeout http_500 http_502 http_503 http_504 - 确认后端是否对健康探测路径(如
/health)也返回了 4xx —— 若有,立即改为统一返回 200 或 503(未就绪时),禁止混用业务状态码
查主动探测参数是否引发 fall/rise 频繁翻转
使用 nginx_upstream_check_module 时,fall=1 或 rise=1 是典型死循环配置:单次探测失败就下线,单次成功就上线,网络抖动或 GC 暂停即可触发秒级震荡。
- 必须设
fall≥3(建议 5)、rise≥2(建议 2–3),避免偶发异常干扰状态 - 检查
interval是否过短(如 1s):探测太密易压垮后端或触发限流,反致探测失败;生产环境建议 ≥5s,高负载时调至 10–30s - 确认
check_http_expect_alive是否包含http_503:若后端 /ready 接口在启动中返回 503,而你又把它当“健康”,就会让未就绪节点提前入池
验防火墙或中间设备是否拦截探测请求但放行业务流量
现象:业务请求能通,健康检查却总失败 → Nginx 认为节点 down → 流量全切走 → 剩余节点压力飙升 → 连带超时增多 → 更多节点被标记 down……最终整组失效。
- 在 Nginx 服务器上手动执行探测命令,比如:
curl -I http://192.168.1.10:8080/health或telnet 192.168.1.10 8080,看是否通 - 对比业务请求路径(如
/api/user)和探测路径(如/health):WAF、安全组、iptables 是否只放行前者?务必把探测路径加入白名单 - 临时改用
type=tcp测试:若 TCP 连通但 HTTP 探测失败,基本锁定是路径/头/证书/重定向等应用层拦截
核对后端服务是否在探测期间自我保护或误响应
某些框架(如 Spring Boot Actuator、K8s readiness probe)默认 /actuator/health 返回 200 即使服务未完全就绪;或在高负载时主动返回 503,但 Nginx 把它当故障下线,反而加剧负载倾斜。
- 后端健康端点必须真实反映“能否处理业务请求”:建议拆分为
/live(进程存活)和/ready(依赖就绪),Nginx 只探/ready - 检查后端日志:是否在收到探测请求后打印了异常堆栈?是否因线程池满、DB 连接耗尽等原因,对所有请求(含探测)统一返回 500?
- 若用 K8s,确认 readiness probe 的初始延迟(
initialDelaySeconds)是否足够长,避免 Nginx 在容器刚启动时就发起探测


















