sentinel.Entry必须在主goroutine调用且e.Exit()严格配对,否则统计归零、流控失效;Entry不可跨协程,defer前须判空e,resourceName统一为"GET:/api/order"格式,系统规则 resourceName 必须设为"default"并传Inbound类型。

sentinel.Entry 必须在主 goroutine 调用,且 e.Exit() 不能漏 —— 否则统计归零、流控形同虚设。这不是配置问题,是埋点逻辑错误。
埋点必须写在 handler 主 goroutine 里,别丢进 go func()
常见错误是把 sentinel.Entry 放在异步 goroutine 中调用,比如:
go func() {
e, b := sentinel.Entry("GET:/api/order")
// ... 业务逻辑
e.Exit() // 这里 exit 无效:goroutine 已退出,上下文丢失
}()
后果是:该请求不计入任何统计窗口,QPS/并发/错误率全为 0,规则永远不触发。
-
Entry()只能在处理 HTTP 请求的主 goroutine(即 Gin/Echo 的 handler 函数体内)调用 - 不要在中间件里提前
Entry后再传给 handler —— 流量类型、资源名可能错位 - 如果 handler 内部要起 goroutine 做异步操作,那它自己需要单独埋点,和主请求无关
resourceName 格式必须统一,Inbound 流量才进系统规则
系统级自适应保护(CPU/Load/RT)只对 resourceName == "default" 且流量类型为 Inbound 的请求生效。接口级限流则用具体路径。
在 Go 中使用 google/wire 实现编译时依赖注入——wire.NewSet、wire.Build、wire.Bind(接口→实现)、wire.Struct、wire.Value、wire.Interface
- 接口限流推荐格式:
"GET:/api/user/{id}"(动词 + 路径模板,不用带参数值) - 系统规则必须用:
"default",且调用时显式传sentinel.WithTrafficType(base.Inbound) - 漏掉
WithTrafficType或传了Outbound,指标就不会汇总到系统维度
defer e.Exit() 前必须判空,否则 panic
sentinel.Entry() 在规则未加载、初始化失败或被拒绝时会返回 e == nil,此时直接 defer e.Exit() 会 panic。
立即学习“go语言免费学习笔记(深入)”;
e, b := sentinel.Entry("GET:/api/order", sentinel.WithTrafficType(base.Inbound))
if b != nil {
// 被限流,返回 429 或自定义错误
return
}
// ✅ 正确写法:判空后再 defer
if e != nil {
defer e.Exit()
}
// 业务逻辑...
- 永远不要写
defer e.Exit()而不检查e != nil - panic 不仅发生在
e.Exit(),也发生在e.BlockError()等后续调用上 -
recover()里补e.Exit()没用 —— goroutine 已终止,统计链路已断
规则加载必须早于第一个请求,且不能 reload
flow.LoadRules() 和 system.LoadRules() 是全局单次操作。反复调用会锁死规则引擎,导致后续所有 Entry 卡住。
- 最佳时机:服务启动时、HTTP server.ListenAndServe() 之前
- 硬编码示例:
flow.LoadRules([]*flow.Rule{{Resource: "GET:/api/order", Threshold: 100, TokenCalculateStrategy: flow.Direct}}) - 动态规则需用
datasource(如 file/nacos),但初始化仍需一次LoadRules触发监听 - 别在 handler 里做
LoadRules—— 高并发下极易死锁
Entry/Exit 配对这件事 —— 它不报错、不崩溃,只悄悄让所有防护失效。你看到监控里 QPS 曲线平直、熔断器从不打开,大概率就是这里漏了一次 defer 或错放了 goroutine。

















