Kratos 不自动防御雪崩,需开发者显式植入熔断、限流、降级、超时四层防护;其熔断器仅含 Closed/Open 两态,用休眠后单请求试探模拟半开,且状态不可监听;Allow() 在 Open 态直返错,Closed 态才统计;触发打开需失败率≥50%且请求数达阈值;休眠期满后首次 Allow() 放行,成功即切回 Closed;MarkSuccess/Failed 需业务手动调用;网关应优先用 BBR 限流替代固定阈值熔断,因其基于 RT、并发等实时指标动态限流,响应更快;BBR 中间件须置于最外层;客户端重试须受熔断器约束,按错误类型差异化处理,禁用 handler 内重试;熔断器不感知下游资源水位,需配合 BBR 或自定义健康检查补全观测。

Kratos 本身不自动防御雪崩,必须由开发者在关键链路显式植入熔断、限流、降级、超时控制四层防护,缺一不可。
kratos pkg/net/netutil/breaker 的 Allow() 行为与状态切换逻辑
Kratos 熔断器只维护 StateClosed 和 StateOpen 两种状态,没有标准的 StateHalfopen;它用“休眠后放行单个请求 + 成功即切回 Closed”模拟半开,但这个过程不暴露状态变量,业务无法监听或干预。
-
Allow()在StateOpen下直接返回错误,不走统计逻辑;只有StateClosed才会累积成功/失败计数 - 触发打开的条件是:最近
requestVolumeThreshold次请求中,失败率 ≥errorRateThreshold(默认 50%),且总请求数 ≥ 阈值 - 打开后进入休眠期(
sleepWindow,默认 60s),到期后首次Allow()调用会放行,若后续MarkSuccess()被调用则立即切回StateClosed;否则继续StateOpen - 注意:
MarkSuccess()和MarkFailed()必须由业务代码在 RPC 调用结束后明确调用,框架不自动包裹 HTTP/gRPC client
网关层用 BBR 限流替代固定 QPS 熔断的必要性
在 Kratos Gateway(kratos-gateway)中,硬配 circuitbreaker.Server() 容易误熔断,因为网关面对的是多路由、多 upstream、混合错误码(4xx vs 5xx)的流量。BBR 限流能更早感知系统瓶颈。
- BBR 不依赖人工设定阈值,而是基于连接建立耗时、响应写入延迟、并发连接数等实时指标,动态推导当前可承受吞吐上限
- 当某 upstream RT 从 20ms 涨到 300ms,BBR 会将该路由并发压到接近 0,比等错误率超 50% 再熔断快 3–5 个 RT 周期
- 必须把
ratelimit.Server()放在中间件链最外层,否则无法采集到完整连接生命周期数据;circuitbreaker.Server()应放在其内层,作为第二道防线 - BBR 默认不区分错误类型,需配合自定义中间件过滤 4xx 请求,避免把业务校验失败计入限流决策
客户端重试必须配合熔断器与退避策略
单纯加重试反而加剧雪崩,Kratos 要求重试行为必须受熔断器约束,并按错误类型差异化处理。
- 对网络错误(如
context.DeadlineExceeded、connection refused)可立即重试 1 次,但必须在Allow()通过后才发起 - 对下游服务级错误(如 gRPC
Code Unavailable、HTTP503)应启用指数退避(exponential backoff),且每次重试前都调用Allow(),失败则跳过重试 - 对业务错误(如 gRPC
Code InvalidArgument、HTTP400)禁止重试,直接返回 - 所有重试逻辑不能写在 handler 内,而应封装进 client 层(如
http.Client的Transport或 gRPCUnaryInterceptor),确保与熔断器共用同一Breaker实例
最容易被忽略的是:Kratos 的熔断器不感知下游真实资源水位(如 goroutine 数、DB 连接池使用率),仅靠请求成功率做决策。这意味着慢节点持续积压请求却未报错时,熔断器完全失敏——必须配合 BBR 或自定义健康检查指标(如 /health?probe=ready 返回 DB 连接池可用数)才能补全这层观测。


















