应直接使用 gobreaker 而非手写状态机或 hystrix-go,它轻量线程安全、原生支持 context.Context;HTTP 熔断必须封装 RoundTripper 而非外层套 Execute,且 ReadyToTrip 和 Timeout 需按 P95 耗时与错误类型调优,降级逻辑须纯内存无副作用。

直接用 gobreaker,别手写状态机,也别碰已归档的 hystrix-go。它轻量、线程安全、原生支持 context.Context,且被 go-zero、kratos 等主流框架采用——自己写大概率在并发激增时漏统计失败、半开态卡死,或把 404 当故障熔断。
为什么不能在外层套 cb.Execute 包 http.Get
这种写法看似简单,实则破坏 HTTP 底层机制:
- 超时控制失效:
http.Client.Timeout和cb.Execute的timeout冲突,ctx 传不进底层 Transport - 连接池复用被破坏:每次调用都新建
http.Client或绕过RoundTrip,导致连接泄漏或复用率暴跌 - 错误类型误判:
net/url.Error、404、sql.ErrNoRows全被计入失败,触发误熔断
正确路径是实现自定义 http.RoundTripper,在 RoundTrip 方法里调用 cb.Execute,透传原始 *http.Request 和 req.Context()。
ReadyToTrip 和 Timeout 怎么配才不翻车
90% 的“熔断不生效”或“一直不恢复”,都出在这俩参数上。默认值只适合本地调试:
-
Timeout(熔断持续时间):设为下游 P95 耗时的 2–3 倍;默认 60s 太长,下游已恢复,你的服务还在拒流 -
ReadyToTrip(触发条件):必须过滤错误类型,例如只将context.DeadlineExceeded、net/http.ErrTimeout视为失败;404、401、业务错误必须放过 -
RequestVolumeThreshold(统计窗口最小请求数):低频服务(如管理后台接口)要调小,否则永远达不到统计条件,熔断器形同虚设
闭包陷阱和降级逻辑怎么写才安全
线上最隐蔽的 panic 往往不是下游挂了,而是闭包引用错变量:
- 循环中闭包捕获
req变量 → 所有请求共用同一地址 →http: Request.Write on Body closedpanic - 正确写法:显式传参,比如
func(req *http.Request) func() (interface{}, error) { return func() { return client.Do(req) } } - 降级逻辑必须纯内存、无副作用:不能查 Redis、不能调配置中心、不能嵌套外部 HTTP 请求;返回兜底 JSON、静态文案,或带
staleheader 的上一次成功响应即可
真正难的不是初始化一个 gobreaker.CircuitBreaker,而是把 RoundTrip 包装对、把错误分类清、把降级做薄——这三处任一出错,熔断就从保护变成阻塞。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











