sentinel.entry必须在gin handler主goroutine中调用,不可跨协程;resourcename须标准化为"get:/api/v1/users/{id}"格式;系统规则resourcename必须为"default"且传inbound类型;热点限流需显式配置paramkey/paramindex及metrictype、controlbehavior。

sentinel.Entry 必须在 Gin handler 主 goroutine 中调用
网关层限流失效的头号原因,就是把 sentinel.Entry 丢进 goroutine 或 defer 链里执行。Sentinel Go 的统计上下文绑定在当前 goroutine,跨协程调用 Entry 会导致指标丢失、规则不生效。
正确姿势是:在每个路由 handler 的最开头、主逻辑开始前调用,且必须配对 e.Exit():
entry := sentinel.Entry("GET:/api/v1/order", sentinel.WithTrafficType(base.Inbound))- 立刻检查
if entry == nil || entry.Blocking() { return c.AbortWithStatusJSON(http.StatusTooManyRequests, ...) } - 再用
defer func() { if entry != nil { entry.Exit() } }()确保退出 —— 注意判空,entry可能为nil(规则未加载或初始化失败)
resourceName 必须按 HTTP 方法 + 路径标准化命名
别用泛化名如 "api" 或 "gateway",否则所有请求挤在一个资源桶里,根本做不到接口级限流。
推荐格式:"GET:/api/v1/users/{id}"、"POST:/api/v1/orders"。路径中带变量的部分保留占位符(如 {id}),不要替换成真实值 —— 否则每个 ID 都变成独立资源,规则爆炸且无法复用。
- 动态路径参数统一用
{xxx},避免fmt.Sprintf("GET:/api/v1/user/%d", uid) - 区分大小写和 trailing slash:
/users和/users/是两个资源 - 同一资源名必须全局一致,改名 = 新资源,旧监控断层、规则失效
系统自适应规则只对 Inbound 流量生效,且 resourceName 必须为 "default"
想让 CPU、Load、RT 这类系统级指标触发保护,不是给某个接口加规则,而是全局入口控制。这时埋点和规则必须严格匹配:
- 埋点时传
sentinel.WithTrafficType(base.Inbound),否则指标不计入系统维度 - 规则里的
resourceName字段必须硬编码为"default",填其他值(包括空字符串)都不生效 - 规则加载要在服务启动早期完成,比如
init()或main()开头,不能每次请求都调system.LoadRules()—— 会锁死规则引擎
示例规则:system.LoadRules([]*system.SystemRule{{MetricType: system.Load, TriggerCount: 8.0}})
热点参数限流需显式提取参数并配置 ParamKey/ParamIndex
网关层做用户 ID、商品 ID 级别的限流,不能只靠资源名。Sentinel Go 的热点规则依赖 ParamFlowSlot,它不会自动解析 query/body,必须人工指定提取位置。
- 若参数在 URL path 中(如
/user/{uid}),用ParamIndex: 0(Gin context.Params[0].Value) - 若参数在 query string(如
?uid=123),优先用ParamKey: "uid",比靠索引更稳定 - 若参数在 JSON body,需实现
ParamFlowArgument接口,否则静默跳过 - 规则中
MetricType(QPS/Concurrency)和ControlBehavior(Reject/Throttling)必须显式设置,漏一项规则加载失败
常见坑:设了 ControlBehavior: flow.Throttling 却没配 MaxQueueingTimeMs,请求会在队列里无限等待。
Entry 调用,而是保证每个资源名语义稳定、每个 Exit 不被遗漏、每个系统规则绑对 "default" —— 这些地方一松动,限流就从保护变成幻觉。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











