gobreaker.execute需显式检查http状态码并转error,仅返回err不解析resp.statuscode会导致5xx漏判;熔断器只依据闭包返回的error计数,故须在闭包内判断resp.statuscode>=500并主动返回error,且readytotrip中应区分错误类型,避免将sql.errnorows等业务正常错误计入失败。

gobreaker.Execute 怎么包 HTTP 请求才不漏错误
直接把 http.Client.Do 塞进 cb.Execute 闭包里,但漏判 5xx 或忽略 resp.StatusCode 是常见错误。熔断器只看闭包返回的 error,不解析响应体或状态码。
- 必须显式检查
resp.StatusCode:比如if resp.StatusCode >= 500 { return nil, fmt.Errorf("http %d", resp.StatusCode) } -
ReadyToTrip函数里别只写err != nil,要区分错误类型——net.ErrTimeout和context.DeadlineExceeded应计入失败,sql.ErrNoRows或404不该触发熔断 - 闭包里别用
http.DefaultClient,确保传入的*http.Client已设好Timeout,且该值 gobreaker.Settings.Timeout,否则熔断计数可能被超时掩盖 - 返回值必须是
(interface{}, error),类型断言不能少:result.(string)或result.(*User),否则 panic
gobreaker.Settings 里哪几个字段最容易配错
90% 的“熔断不生效”或“卡在 open 状态”都出在这三个字段上,不是逻辑问题,是配置漂移。
-
Interval:默认是 60 秒滑动窗口,但高 QPS 服务建议缩到 10–30 秒,否则低频调用下一次失败就满阈值 -
SleepWindow:名字误导性强,它其实是 “open 状态持续最短时间”,不是“休眠时长”。默认 60 秒太长,生产环境设为 10–30 秒更合理 -
MaxRequests:半开状态下允许试探的请求数。设为 1 容易恢复慢,设为 100 可能压垮刚恢复的下游;3–5 是安全起点
为什么 cb.Execute 后下游请求还没中断
熔断器不 cancel 已发起的 goroutine,它只决定“这次要不要执行”。很多人误以为加了熔断,context.WithTimeout 就自动生效,其实不是。
-
cb.Execute包裹的是函数体,不是 context 本身;必须在闭包内用http.NewRequestWithContext(ctx, ...)显式透传 - 如果闭包里用了
time.Sleep或阻塞 I/O,会拖慢整个状态判断周期,导致熔断滞后 - 别指望熔断器替你做重试——
gobreaker不重试、不降级,只返回gobreaker.ErrOpenState,后续逻辑得自己接住并 fallback
多个下游服务共用一个 CircuitBreaker 实例会怎样
会串扰统计,A 服务故障拉垮 B 服务的熔断状态,这是线上真实踩过的坑。
- 按下游服务维度初始化:比如
cbUserService、cbPaymentService,名字字段也建议对应 -
gobreaker.CircuitBreaker实例是线程安全的,可全局复用,但绝不能跨依赖混用 - 不要为每个 HTTP 方法(GET/POST)单独建实例,按服务边界划分,而非接口粒度
ReadyToTrip 的判定逻辑和 OnStateChange 回调里的同步阻塞——前者写错会导致误熔或不熔,后者写个日志发 HTTP 请求,可能让整个熔断器卡死。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











