微服务网关集成Sentinel实现动态限流策略推送

4次阅读

限流规则推送后不生效,首要检查 sentinel-dashboard 与网关的通信链路是否畅通,确认网关已注册到 dashboard 机器列表、依赖正确(如 sentinel-spring-cloud-gateway-adapter)、配置了正确的 dashboard 地址及 nacos dataid,并注意资源维度(routeid/resourceid)匹配与 blockexception 响应定制。

微服务网关集成Sentinel实现动态限流策略推送

限流规则推送后不生效?检查 sentinel-dashboard 和网关的通信链路

Sentinel 网关流控规则必须通过 sentinel-dashboard 推送到网关应用内存,不是写配置文件就完事。常见现象是规则在控制台点“推送”后,sentinel-dashboard 日志显示成功,但网关实际没拦截请求——大概率是网关没连上 dashboard 或没拉取规则。

  • sentinel-dashboard 默认监听 8080,网关需配置 spring.cloud.sentinel.transport.dashboard 指向该地址,且网络互通(别忽略防火墙或 k8s Service DNS 解析)
  • 网关启动后会主动向 dashboard 注册,dashboard 的「机器列表」里必须能看到该网关实例(IP + 端口),否则规则根本不会下发
  • 确认网关依赖了 sentinel-spring-cloud-gateway-adapterspring cloud Gateway 场景)或 sentinel-zuul-adapter(Zuul 1.x),仅引入 sentinel-web-servlet 不起作用
  • 若用 Nacos 作规则存储,注意网关侧要额外加 sentinel-datasource-nacos,且 spring.cloud.sentinel.datasource.ds.nacos 配置项中的 dataId 必须和 dashboard 中配置的完全一致(包括后缀 -gw-flow-rules

网关限流维度选错:routeId vs resourceId 怎么定?

Spring Cloud Gateway 下,Sentinel 默认按 routeId 限流,但很多场景需要更细粒度——比如同一 route 下对 /user/{id} 和 /user/export 做不同阈值控制。这时就得切到 resourceId 维度,但切换方式容易踩坑。

  • 默认限流 key 是 routeId,对应 dashboard 中「API 分组」下拉框里看到的 route 名称;若想按自定义资源名限流,得在网关配置中关闭自动埋点:spring.cloud.sentinel.Filter.enabled=false,再手动用 @SentinelResourceSphU.entry() 包裹逻辑
  • 手动埋点时,resourceId 建议带业务标识前缀(如 gw:user:detail),避免和默认 routeId 冲突;dashboard 新建规则时,“资源名”字段必须严格匹配该字符串
  • 注意:Zuul 网关不支持 routeId 自动识别,必须手动指定 resourceId,否则规则永远不命中

动态规则推送失败报 java.lang.NoClassDefFoundError: com/alibaba/csp/sentinel/cluster/server/ClusterServerConfigManager

这个错误说明网关应用缺了集群流控服务端模块,但你其实并不需要它——网关做的是客户端限流,sentinel-cluster-server-default 是给独立部署的 Token server 用的,强行引入反而引发类冲突。

  • 检查 pom.xml 或 build.gradle,删掉所有含 sentinel-cluster-server 的依赖(包括 sentinel-cluster-server-defaultsentinel-cluster-server-state-transfer
  • 网关只需保留:sentinel-spring-cloud-gateway-adapter + sentinel-datasource-nacos(如果用了 Nacos)+ sentinel-transport-simple-http(用于和 dashboard 通信)
  • 若误加了 sentinel-cluster-client-default,也会导致启动失败,它只适用于接入 token server 的场景,网关直连 dashboard 时不需要

限流响应体被覆盖:网关返回 429 却看不到自定义提示

默认情况下,Sentinel 触发限流会抛 BlockException,网关全局异常处理器可能把它吞掉,最终返回空体或默认 429 页面。想透出 json 提示,得接管降级逻辑。

  • Spring Cloud Gateway 下,通过实现 BlockRequestHandler 接口并注册为 Bean 来定制响应体,例如返回 {"code":429,"msg":"限流中"}
  • 别直接在 GlobalFilter 里 try-catch BlockException —— Sentinel 的异常是在 filter 链末端抛出的,此时 response 已提交,再写 body 会触发 IllegalStateException: Response already committed
  • 若用 spring boot 2.6+,注意 WebExceptionHandler 的 order 值必须小于 NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER - 1,否则写不了 body

Sentinel 网关限流真正卡住人的,从来不是规则怎么配,而是 dashboard 和网关之间那条看不见的通信链路,以及资源维度和异常处理这两个必须显式干预的环节。

text=ZqhQzanResources