Sentinel 进阶教程 - 中级篇(2024 年)
大纲
- Sentinel 入门教程 - 基础篇(2020 年)
- Sentinel 入门教程 - 中级篇(2020 年)
- Sentinel 入门教程 - 整合篇(2020 年)
- Sentinel 进阶教程 - 基础篇(2024 年)
- Sentinel 进阶教程 - 中级篇(2024 年)
- Sentinel 进阶教程 - 整合篇(2024 年)
前言
官方资源
版本说明
在本文的所有案例中,各个组件统一使用以下版本:
组件 | 版本 | 说明 |
---|---|---|
Spring Boot | 3.2.0 | |
Spring Cloud | 2023.0.0 | |
Spring Cloud Alibaba | 2022.0.0.0 | |
Sentinel Dashboard | 1.8.7 |
代码下载
- 本文完整的案例代码可以从 这里 下载得到。
Sentinel 注解支持
官方文档
@SentiinelResource 的概述
@SentiinelResource
是 Sentinel 官方提供的一个流量防卫防护组件注解,用于指定防护资源,对配置的资源进行流量控制、熔断降级等功能。@SentiinelResource
注解的底层源码和注释如下:
1 |
|
@SentiinelResource 的使用
默认不使用注解的行为表现
案例目标
Sentinel 使用接口的 URL 地址作为资源名进行限流 + 返回默认的限流提示。
- Java 接口代码
1 |
|
- Sentinel 控制台添加流控规则
- 通过浏览器快速多次访问
/rateLimit/byUrl
接口时,会返回默认提示信息Blocked by Sentinel (flow limiting)
,说明接口被限流了。
提示
在 Sentinel 控制台添加流控规则时,资源名默认就可以是请求的接口路径(URL),可以自行修改。同一微服务应用内,资源名必须唯一。不同微服务应用之间,资源名可以重复。
使用注解自定义限流的提示
案例目标
Sentinel 按照资源名称进行限流 + 返回自定义的限流提示。
若不希望 Sentinel 使用默认的限流提示 Blocked by Sentinel (flow limiting)
,而是想返回自定义限流的提示,可以使用 @SentiinelResource
注解 的 blockHandler
属性来实现。
- Java 接口代码
1 |
|
- Sentinel 控制台添加流控规则
- 通过浏览器快速多次访问
/rateLimit/byResource
接口时,会返回自定义提示信息目前访问人数较多,请稍后再试!
,说明接口被限流了。
使用注解自定义降级处理逻辑
案例目标
Sentinel 按照资源名称进行限流 + 返回自定义的限流提示 + 服务降级处理(Fallback)。
使用 Sentinel 的时候,若希望在接口调用抛出业务异常(不包括 BlockException 异常)时,执行指定的降级处理逻辑,可以使用 @SentiinelResource
注解 的 fallback
属性来实现。特别注意,这里的降级处理只是在接口调用抛出业务异常时,简单执行指定的降级处理逻辑(比如返回兜底数据),并没有实现熔断的功能。若需要使用熔断功能,可以使用 Sentinel 提供的 熔断规则。
- Java 接口代码
1 |
|
- Sentinel 控制台添加流控规则
- 通过浏览器快速多次访问
/rateLimit/doAction/1
接口时,会返回自定义提示信息目前访问人数较多,请稍后再试!
,说明接口频繁调用时,成功被限流了。 - 通过浏览器单次访问
/rateLimit/doAction/0
接口时,会返回自定义的降级处理结果服务出错啦,请稍后再试!
,说明调用接口抛出业务异常(不包括 BlockException)时,成功被降级处理了。
使用总结
@SentinelResource
注解的blockHandler
属性,主要针对 Sentinel 配置了规则后出现的违规情况(比如触发了流控规则、熔断规则、热点规则等)进行处理。@SentinelResource
注解的fallback
属性,主要针对程序在运行时抛出了业务异常(不包括 BlockException 异常),需要进行降级处理的情况。@SentinelResource
注解的blockHandler
和fallback
属性可以共存,也就是可以互相配合使用。
Sentinel 热点规则
官方文档
热点规则
热点规则的概述
何为热点?热点即经常访问的数据。在很多时候,我们希望统计某些热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:
- 使用商品 ID 作为参数,统计一段时间内最常购买的商品 ID,并进行限制。
- 使用用户 ID 作为参数,针对一段时间内频繁访问的用户 ID,进行限制。
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制方式,仅对包含热点参数的资源调用生效。
Sentinel 利用 LRU(最长时间未使用)策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。值得一提的是,热点参数限流支持集群模式。
LRU 算法与 LFU 算法
LRU (Least Recently Used)
:根据最近使用的顺序来淘汰数据,即淘汰最长时间未被访问的数据。LFU (Least Frequently Used)
:根据数据被访问的频率来淘汰数据,即淘汰访问频率最低的数据。
热点规则的添加
在 Sentinel 控制台里,添加热点规则的步骤如下:
热点参数规则(ParamFlowRule)类似于流量控制规则(FlowRule),主要有以下配置项:
属性 | 说明 | 默认值 |
---|---|---|
resource | 资源名,必填 | |
count | 限流阈值,必填 | |
grade | 限流模式 | QPS 模式 |
durationInSec | 统计窗口时间长度(单位为秒),从 1.6.0 版本开始支持 | 1s |
controlBehavior | 流控效果(支持快速失败和匀速排队模式),从 1.6.0 版本开始支持 | 快速失败 |
maxQueueingTimeMs | 最大排队等待时长(仅在匀速排队模式生效),从 1.6.0 版本开始支持 | 0ms |
paramIdx | 热点参数的索引,必填,对应 SphU.entry(xxx, args) 中的参数索引位置 | |
paramFlowItemList | 参数例外项,可以针对指定的参数值单独设置限流阈值,不受前面 count 阈值的限制。仅支持基本类型和字符串类型 | |
clusterMode | 是否是集群参数流控规则 | false |
clusterConfig | 集群流控相关配置 |
热点规则的使用
- Java 接口代码
1 |
|
- Sentinel 控制台添加热点规则
特别注意
在 Sentinel 控制台添加热点规则时,资源名必须是 @SentinelResource
注解的 value
属性的值,不能是接口的 URL 地址,否则热点参数限流不会生效。
- 测试案例代码
- (1) 通过浏览器快速多次访问
/testHotKey?p1=abc
接口,发现会返回自定义的限流提示信息hot key rate limit
,说明热点参数限流生效。 - (2) 通过浏览器快速多次访问
/testHotKey?p1=abc&p2=efg
接口,发现也会返回自定义的限流提示信息hot key rate limit
,说明只要请求含有指定的参数,热点参数限流都会生效。 - (3) 通过浏览器快速多次访问
/testHotKey?p2=efg
接口,发现返回的结果都是success
,说明只要请求不含有指定的参数,即使不断访问接口也不会触发热点参数限流。
- (1) 通过浏览器快速多次访问
参数例外项配置
参数例外项的概述
在上述案例中,演示了接口携带第一个参数 p1
,当 QPS 超过 1 秒 1 次时,接口马上被限流。但是,面对复杂易变的业务需求,往往会有特殊情况需要额外处理。
- 正常限流
- 接口携带第一个参数
p1
,当 QPS 达到预设阀值时立刻被限流。
- 接口携带第一个参数
- 特殊限流
- 希望当
p1
参数是某个特殊值时,QPS 到达预设阀值后热点规则突然例外(失效),它的限流阀值跟平时不一样。 - 比如:当
p1
参数的值等于 5 时,QPS 阀值可以允许达到 200 或者其他值。
- 希望当
参数例外项的使用
- Java 接口代码
1 |
|
- Sentinel 控制台添加热点规则 + 参数例外项
- 测试案例代码
- (1) 通过浏览器快速多次访问
/testHotKey?p1=abc
接口,当 QPS 达到超过 1 秒 1 次时,发现会返回自定义的限流提示信息hot key rate limit
,说明普通的热点参数限流生效。 - (2) 通过浏览器快速多次访问
/testHotKey?p1=mnt
接口,当 QPS 达到超过 1 秒 5 次时,才会返回自定义的限流提示信息hot key rate limit
,说明参数例外项的热点参数限流生效。
- (1) 通过浏览器快速多次访问
特别注意
使用参数例外项时,参数必须是基本类型或者 String 类型。
Sentinel 授权规则
官方文档
授权规则的概述
在很多时候,往往需要根据调用来源来判断该次请求是否允许放行,这时候可以使用 Sentinel 提供的授权规则(也叫黑白名单控制)来实现。授权规则根据资源的请求来源(Origin)限制资源是否通过,若配置白名单则只有请求来源位于白名单内时才可通过;若配置黑名单则请求来源位于黑名单时不通过,其余的请求都通过。
提示
调用方信息是通过 ContextUtil.enter(resourceName, origin)
方法中的 origin
参数传入。
授权规则的添加
在 Sentinel 控制台里,添加热点规则的步骤如下:
授权规则(AuthorityRule)非常简单,主要有以下配置项:
属性 | 说明 | 默认值 |
---|---|---|
resource | 资源名,即限流规则的作用对象。 | |
limitApp | 对应的黑名单 / 白名单,不同 origin 用 , 分隔,如 appA,appB 。 | |
strategy | 限制模式,AUTHORITY_WHITE 为白名单模式,AUTHORITY_BLACK 为黑名单模式,默认为白名单模式。 | AUTHORITY_WHITE |
授权规则的使用
- Java 接口的代码
1 |
|
- 自定义请求来源转换器,需要实现
RequestOriginParser
接口,目的是告知 Sentinel 从哪里获取请求来源
1 |
|
- Sentinel 控制台添加授权规则
- 测试案例代码
- (1) 通过浏览器访问
/empower?serverName=appC
接口,会返回正确结果success
。 - (2) 通过浏览器访问
/empower?serverName=appA
接口,发现会返回Blocked by Sentinel (flow limiting)
,说明授权规则生效了。 - (3) 通过浏览器访问
/empower?serverName=appB
接口,发现会返回Blocked by Sentinel (flow limiting)
,说明授权规则生效了。
- (1) 通过浏览器访问
Sentinel 配置规则持久化
由于一旦重启微服务应用,Sentinel 已配置的规则就会丢失,因此生产环境需要将 Sentinel 配置规则持久化。比如,将流控规则持久化进 Nacos 保存后,只要 Nacos 里面的配置信息不删除,Sentinel 的流控规则就会持续有效。值得一提的是,为了微服务重启后不丢失 Sentinel 已配置的规则,还可以使用 Sentinel 提供的 API 来自定义配置规则,也就是说通过代码的方式定义(写死) Sentinel 配置规则,比如 GatewayRuleManager.loadRules(rules)
,缺点是配置规则不能随意更改(不支持实时更新)。Sentinel 官方推荐注册动态规则源来实现动态推送,比如 GatewayRuleManager.register2Property (property)
。
特别注意
- (1) Sentinel 网关流控规则的数据源类型是
gw-flow
,若将网关流控规则的数据源类型指定为flow
则不会生效,定义在com.alibaba.cloud.sentinel.datasource.RuleType
枚举类中。 - (2) 当 Sentinel 控制台从 Nacos 中加载完配置规则后,如果在 Sentinel 控制台修改配置规则,那么是不会将配置规则的更改同步到 Nacos 中的,也就是说配置规则的更改在下次微服务应用重启后会失效。正确的做法是在 Nacos 中更改 Sentinel 配置规则,因为 Sentinel 控制台会订阅 Nacos 中的配置规则变更,也就是 Sentinel 通过 Nacos 可以支持配置规则的实时更新。
引入依赖坐标
1 | <!-- Sentinel --> |
提示
如果在项目中,已经使用了 Nacos 作为服务注册中心或者配置中心,则项目无需做任何改动,只需要正常引用上面的 Maven 依赖和添加下面的 YML 配置信息即可实现 Sentinel 配置规则持久化。
添加测试代码
1 |
|
添加 YML 配置信息
1 | spring: |
上面配置的 rule-type
参数的值来自 com.alibaba.cloud.sentinel.datasource.RuleType
枚举类,常用的值有以下几个:
上面配置的 datasource
可以有多个,可以理解为允许有多个不同类型的控制规则(如流量规则、熔断规则、热点规则等),如下图所示:
Nacos 添加流控规则
提示
这里只简单演示如何将 Sentinel 的流控规则配置信息持久化到 Nacos 中,如果是持久化熔断规则或者热点规则等其他配置信息,具体的 JSON 配置内容请自行查阅官方文档。
首先将 Sentinel 流控规则的配置信息转换为 JSON 配置内容:
1 | [ |
Sentinel 流控规则的 JSON 配置内容说明:
参数 | 说明 |
---|---|
resource | 资源名称 |
limitApp | 来源应用 |
grade | 阈值类型,0 表示并发线程数,1 表示 QPS |
count | 单机阈值 |
strategy | 流控模式,0 表示直接,1 表示关联,2 表示链路 |
controlBehavior | 流控效果,0 表示快速失败,1 表示 Warm Up,2 表示排队等待 |
clusterMode | 是否集群 |
然后将 Sentinel 流控规则的 JSON 配置内容添加到 Nacos 中:
最后在 Nacos 中 Sentinel 流控规则的配置信息如下:
案例代码测试
- (1) 启动微服务应用。
- (2) 通过浏览器访问微服务应用的
/rateLimit/byUrl
接口,等待几秒中,让 Sentinel 控制台发现微服务应用的存在。 - (3) 通过浏览器访问 Sentinel 控制台的管理页面,点击
流控规则
菜单项,即可以看到在 Nacos 中添加的流控规则配置信息(如下图所示)。如果看不到对应的配置信息,可以多刷新几次页面试试。
- (4) 通过浏览器快速多次访问
/rateLimit/byUrl
接口,当 QPS 达到超过 1 秒 1 次时,接口会返回默认提示信息Blocked by Sentinel (flow limiting)
,说明 Sentinel 的流控规则生效了。 - (5) 重启微服务应用,再次通过浏览器快速多次访问
/rateLimit/byUrl
接口,当 QPS 达到超过 1 秒 1 次时,接口仍然会被限流。