应直接使用sony/gobreaker,按下游服务维度独立创建circuitbreaker实例,命名标识服务(如"payment-service-call"),配置maxrequests≥10、timeout=15s、interval=30s~2m;execute仅包裹实际调用(如client.do(req)或stub.getuser(ctx,req)),主动将5xx转error,fallback须纯内存无副作用,并配合context.withtimeout与prometheus指标监控。

直接用 sony/gobreaker,别自己手写状态机——它被 go-zero 和 kratos 大量验证过,滑动窗口、半开探测、无外部依赖,开箱即用。
为什么必须按依赖隔离创建 gobreaker.CircuitBreaker 实例
熔断器不是全局开关,而是每个下游服务专属的“保险丝”。共用一个实例会导致 A 服务故障把 B 服务也拖垮。
- 每个 HTTP 客户端、gRPC 连接、数据库连接池都应配独立
cb实例,命名带上服务标识,比如Name: "payment-service-call" -
MaxRequests建议 ≥10,设成 1 容易误判:半开刚进就因单次失败又切回 Open -
Timeout是“熔断后多久尝试半开”,不是调用超时——设 15s 比较合理;设成 60s 会导致下游已恢复,你还在休眠 -
Interval控制滑动窗口重置周期,30s~2m 之间选,太短(如 5s)会把网络抖动当持续故障
cb.Execute 必须只包裹实际调用动作,不是整个 client
常见错误是把 http.Client 或 grpc.ClientConn 整个塞进 Execute,其实只需包住真正发起请求的那一行。
- HTTP 场景:只包
client.Do(req),不是http.DefaultClient - RPC 场景:只包
stub.GetUser(ctx, req),不是 stub 初始化 -
Execute第二个参数函数必须返回error,且仅当err != nil才计入失败统计 - HTTP 5xx 响应要主动转 error:
if resp.StatusCode >= 500 { return nil, fmt.Errorf("5xx from upstream") }
降级逻辑必须无依赖、快、可嵌入 cb.Execute 的 fallback 参数
熔断器本身不提供降级能力,gobreaker 的第三个参数才是 fallback 入口。这里写的代码,会在 ErrOpenState 或执行失败时触发。
- 不能调外部服务、不能查 DB、不能 sleep —— 否则降级本身变成新瓶颈
- 推荐方案:返回本地缓存数据、静态默认值、或预计算好的兜底结果(比如“热门商品列表”替代实时推荐)
- fallback 函数签名必须匹配主函数:返回
(interface{}, error),且内部不要 panic - 务必配合
context.WithTimeout使用——熔断只管开关,超时得你自己控,否则 fallback 也可能卡住
最容易被忽略的是指标暴露和状态观测:gobreaker.Metrics 要接入 Prometheus,重点盯 circuit_breaker_state、circuit_breaker_requests_total 和 circuit_breaker_fallback_total。没监控的熔断,等于在黑盒里拉闸。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











