Sentinel Go 应统一使用 sentinel.Entry 实现限流熔断,避免手写 rate.Limiter;需按业务语义定义稳定资源名、区分 blockHandler 与 fallback、配置匹配场景的熔断策略,并通过 etcd 动态加载规则。

限流直接用 sentinel.Entry,别自己手写 rate.Limiter
自己用 rate.Limiter 做单机限流,看似简单,但一上生产就暴露问题:无法跨实例同步状态、不支持动态规则、没熔断联动、监控数据难聚合。Sentinel Go 的 sentinel.Entry 是统一入口,背后自动对接滑动窗口统计、规则热加载、指标上报,省掉大量胶水代码。
常见错误是把 sentinel.Entry 放在 handler 外层全局调用,导致所有请求共用一个资源名,压根起不到按接口/方法粒度限流的效果。正确做法是每个逻辑单元定义独立资源名:
-
sentinel.Entry("user-service:query-by-id")—— 按业务语义命名,别用泛化名如"api" - 资源名必须稳定:改名 = 新资源,旧规则失效,监控断层
- 调用后必须检查返回的
error,nil才代表放行;非nil时直接返回http.StatusTooManyRequests或自定义降级响应
熔断降级必须区分「慢调用」和「异常比例」两种策略
Sentinel Go 的 CircuitBreaker 不是开/关二值开关,而是基于实时指标自动切换 State(StateClosed / StateOpen / StateHalfOpen)。选错策略会导致该熔断时不熔、不该熔时乱熔。
典型误配:
立即学习“go语言免费学习笔记(深入)”;
- 对数据库查询设「错误比例」熔断 → 网络抖动引发短暂超时,但错误率未达标,结果持续重试拖垮连接池
- 对第三方 HTTP 调用设「慢调用比例」→ 响应时间波动大,阈值设 800ms 还是 1200ms 很难拍板,不如直接用「异常比例 + 半开探测」更稳
推荐组合:
- 内部 RPC 调用:用
SlowRatioStrategy,阈值设为依赖服务 P95 RT + 20% - 外部 API 或 DB:用
ErrorRatioStrategy,错误率 > 0.5 且窗口内错误数 ≥ 5 触发熔断
降级响应不能只靠 fallback 函数,得配合 blockHandler 和真实兜底数据
Sentinel 的 fallback 只在熔断触发时执行,而 blockHandler 是限流被拒时的处理函数——两者职责不同,混用会漏场景。比如用户刷接口被限流,blockHandler 返回缓存商品列表;而支付服务宕机触发熔断,fallback 返回“支付暂不可用,请稍后再试”。
容易踩的坑:
-
fallback函数里再发起新 Sentinel 资源调用 → 可能造成嵌套熔断或死循环 -
blockHandler返回硬编码字符串 → 前端无法解析,应返回与正常接口结构一致的 JSON,字段值填默认值或空数组 - 没预热降级数据:首次降级时才去查缓存或读本地文件,反而增加延迟 → 提前加载好兜底数据到内存 map 或 sync.Pool
动态规则必须走 etcd 或 Nacos,别用本地 JSON 文件
本地 json 配置改完要重启进程,线上根本不可行。Sentinel Go 0.3.0+ 原生支持 etcd 数据源,规则变更秒级生效。
实操要点:
- etcd key 路径按环境隔离,例如
/sentinel/rules/prod/user-service,避免测试规则污染生产 - 规则结构里
resource字段必须与代码中sentinel.Entry("xxx")的字符串完全一致,大小写、连字符都不能错 - 上线前用
sentinel.GetRules()主动拉取一次规则并 log,确认加载成功;否则静默失败,限流形同虚设
最常被忽略的是规则生效延迟:etcd watch 有毫秒级延迟,加上客户端本地缓存刷新周期(默认 1s),从配置变更到实际生效可能有 1–2 秒空窗。高敏感业务需在控制台人工触发 sentinel.LoadRules() 强制刷新。


















