Nginx原生不支持断路器,但可通过max_fails/fail_timeout实现节点级熔断、limit_req+error_page实现接口级降级、OpenResty+Lua实现Closed/Open/Half-Open三态逻辑熔断。

Nginx 本身不提供原生断路器(Circuit Breaker)能力,但可通过组合配置与扩展模块,在负载均衡层实现贴近生产可用的熔断降级策略。核心思路是:用健康检查做节点级隔离、用限流和错误响应做路径级干预、用 OpenResty + Lua 实现状态感知的主动熔断。
基于 upstream 的被动熔断(最简可用)
这是 Nginx 原生支持的最小可行方案,适用于快速规避已确认故障节点:
max_fails和fail_timeout共同构成“失败窗口”机制
当某后端在fail_timeout秒内连续失败max_fails次(如连接超时、502/503),Nginx 将其标记为down,并在该fail_timeout周期内不再转发请求-
配置示例:
upstream order_service { server 192.168.1.10:8080 max_fails=3 fail_timeout=30s; server 192.168.1.11:8080 max_fails=3 fail_timeout=30s; server 192.168.1.12:8080 backup; # 故障时自动切至备用节点 } -
注意事项:
- 失败判定依赖
proxy_next_upstream设置,需显式启用:proxy_next_upstream error timeout http_500 http_502 http_503 http_504; -
fail_timeout不是冷却期,而是“标记为 down 后等待多久再尝试恢复”,不是熔断状态保持时间
- 失败判定依赖
接口级限流 + 错误率联动降级
单纯踢节点不够细粒度,业务常需对 /api/v1/payment 这类高危接口单独防护:
-
使用
limit_req_zone定义按 URI 或用户身份的限流维度limit_req_zone $uri zone=api_limit:10m rate=10r/s; limit_req_zone $http_x_user_level$uri zone=user_api_limit:10m rate=50r/s;
-
在 location 中绑定并设置突发缓冲:
location /api/v1/payment { limit_req zone=api_limit burst=20 nodelay; proxy_pass http://payment_backend; proxy_intercept_errors on; error_page 500 502 503 504 /fallback_payment.html; } /fallback_payment.html可返回静态兜底页,或配合proxy_pass转向降级服务(如本地缓存接口、备用支付通道)
OpenResty 实现三态逻辑熔断(推荐进阶方案)
要真正支持 Closed → Open → Half-Open 状态切换、按路径统计错误率、自动试探恢复,必须引入 Lua:
-
基础准备:
lua_shared_dict fuse_state 10m; # 存储每个 URI 的熔断状态、计数器、最后失败时间
-
在
access_by_lua_block中判断是否熔断:local key = ngx.var.uri local state = ngx.shared.fuse_state:get(key .. ":state") or "closed" if state == "open" then return ngx.exit({ status = 503, body = '{"code":503,"msg":"service unavailable"}' }) elseif state == "half-open" then -- 仅允许固定数量试探请求(如3个),其余仍拦截 local count = ngx.shared.fuse_state:incr(key .. ":halfopen_count", 1) if count > 3 then ngx.shared.fuse_state:set(key .. ":state", "open") return ngx.exit(503) end end -
在
log_by_lua_block中更新状态:local key = ngx.var.uri local status = tonumber(ngx.var.status) if status >= 500 and status < 600 then ngx.shared.fuse_state:incr(key .. ":failures", 1) ngx.shared.fuse_state:set(key .. ":last_fail", ngx.time()) else ngx.shared.fuse_state:incr(key .. ":successes", 1) end -- 滑动窗口清理:超时数据自动失效(需额外定时器或 TTL 设计) 半开恢复逻辑可封装为独立函数,满足连续 N 次成功即切回
closed
降级行为的多样化落地
熔断生效后,不能只返回 503,应按场景提供弹性响应:
- 返回预设 JSON 错误体(前端可识别并触发本地重试或提示)
-
proxy_pass到内部降级服务(如/internal/fallback/order) - 读取 Redis 缓存中的兜底数据(通过
resty.redis) - 写入 Kafka 或 RocketMQ 异步队列,后续补偿处理
不复杂但容易忽略


















