Nginx可通过upstream被动健康检查+proxy_next_upstream+超时设置实现轻量级熔断:max_fails=1与fail_timeout=5s实现秒级节点摘除与试探恢复,proxy_next_upstream指定5xx等失败条件触发重试与统计,配合connect/send/read超时避免连接阻塞,并支持backup降级及error_page兜底返回200降级响应。

Nginx 本身不维护服务状态,也没有内置断路器(Circuit Breaker)模型,所以不能像 Hystrix 那样实现标准的 Closed/Open/Half-Open 三态熔断。但通过 upstream 的被动健康检查机制 + proxy_next_upstream 策略 + 合理超时设置,就能在 nginx.conf 中落地实用、可触发、秒级响应的故障熔断逻辑。
关键不是“模拟熔断”,而是让 Nginx 在真实故障发生时,快速感知、立即避让、有限重试、自动恢复——这正是生产环境最需要的“轻量级熔断”。
配置 upstream 实现节点级自动摘除
这是最核心、开箱即用的熔断基础。Nginx 会根据实际请求失败情况,临时下线不可用节点:
upstream payment_backend {
# 单次失败即摘除,5秒后自动试探恢复(真正秒级响应)
server 192.168.1.20:8080 max_fails=1 fail_timeout=5s;
server 192.168.1.21:8080 max_fails=1 fail_timeout=5s;
# 可选:配置备用降级服务(如本地静态页或缓存接口)
server 127.0.0.1:8081 backup;
}-
max_fails=1:只要一次有效失败(非业务 4xx),就标记为 down -
fail_timeout=5s:5 秒后首个新请求会主动重连,成功则重新纳入轮询 -
backup节点仅在所有主节点都不可用时启用,适合返回兜底响应
⚠️ 注意:这个机制默认不统计 5xx 响应,必须配合 proxy_next_upstream 显式启用。
在 location 中启用失败识别与重试策略
光配 upstream 不够,Nginx 必须知道“哪些响应算失败”,才能计入 max_fails 计数:
location /api/v1/pay {
proxy_pass http://payment_backend;
# 关键:定义哪些情况触发重试 & 计入失败统计
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
proxy_next_upstream_tries 2; # 最多转发 2 次(本节点 + 1 次换节点)
proxy_next_upstream_timeout 8s; # 整个重试链路总耗时上限
# 防止重试放大压力,建议设上限
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}-
error:底层连接异常(拒绝、重置) -
timeout:含proxy_connect_timeout/proxy_send_timeout/proxy_read_timeout触发的超时 -
不要加
http_400http_401http_404:它们是业务正常反馈,加入会导致健康节点被误踢
设置上游超时参数,避免 worker 被卡住
慢响应比直接失败更危险——它会让连接长期 hang 住,耗尽 worker 连接池:
# 在 http 或 server 块中统一设置 proxy_connect_timeout 3s; # 建连超时,3 秒连不上就换节点 proxy_send_timeout 5s; # 发请求给后端,5 秒内发不完就放弃 proxy_read_timeout 8s; # 等后端响应头+首块体,8 秒没收到就断连记失败
这些超时值要略小于后端自身的超时设定(例如后端设 10s,Nginx 设 8s),确保 Nginx 先于后端“主动放弃”,从而驱动 max_fails 统计和节点摘除。
可选:添加降级响应兜底
当所有主节点不可用、且 backup 也未配置或失效时,可返回统一降级内容:
location /api/v1/pay {
proxy_pass http://payment_backend;
proxy_intercept_errors on; # 允许拦截 5xx 错误
# 所有 upstream 失败后,返回本地降级 JSON
error_page 500 502 503 504 =200 /_fallback.json;
}
location = /_fallback.json {
internal;
add_header Content-Type "application/json; charset=utf-8";
return 200 '{"code":503,"msg":"service_unavailable","data":{}}';
}这样前端收到的是合法 200 + 降级数据,而非裸 503,便于统一处理。
不复杂但容易忽略


















