六 、流量控制框架-Sentinel
6.1 Sentinel 简介
Sentinel
是阿里开源的流量控制框架,从限流、降级、熔断、三个维度保护服务;
基于上游服务和下游服务这一情景,再去了解这三个限流维度(维度:限流 < 降级 < 熔断)
;每个服务都是通过接口对外提供服务,客户端请求服务和服务之间的相互调用,当服务的访问流量QPS
到达指定量级就会触发相应的流控规则。
- 限流:对服务资源的访问流量实行限制措施,单位时间内只允许一定量的访问通过,一般是让溢出的访问排队等候。
- 降级:当服务出现故障或者出现其他不能提供服务的情况下,返回预设的静态数据或页面,给予友好提示。即使心已经碎了,也要面露微笑。
- 熔断:直接拒绝访问。
6.2 下载运行Sentinel控制台
下载地址:https://github.com/alibaba/Sentinel/releases
这里下载了1.7.1
版本的jar
包,下载完直接运行就好,账号密码都是sentinel
。
默认端口是8080
,可以用-Dserver.port=xxxx
指定端口。
访问仪表盘可以看到目前是没有数据的状态,因为还没有任何服务和它交互。
6.3 搭建一个Sentinel测试项目
6.4 添加对应配置
直接在Nacos
上添加配置
custom:
info: sentinel-sample provider
custom:
info: sentinel-sample consumer
6.5 访问消费者测试接口
http://localhost:8041/test
http://localhost:8041/getConfig
可以看到Sentinel
仪表盘监控到了访问。组件测试没问题。
6.6 使用Sentinel常用规则
6.6.1 流控规则
链接:流控规则
6.6.2 降级规则
Sentinel
降级主要有三个策略:RT
、异常比例
、异常数
。
链接:降级规则
6.6.3 系统规则
前面的流控规则和降级规则都是针对单个资源而言
系统规则则是针对整个应用服务的流量控制规则
它有四种阈值类型:
- LOAD:负载,当系统负载超过阈值,就会触发保护机制(
LOAD
规则只能在Linux
、Unix-like
系统上生效) - RT:当整个应用所有资源的平均响应时间达到阈值,触发保护机制。
- 线程数:当整个应用的并行请求数达到设定阈值,触发保护机制。
- 入口QPS:当整个应用的请求数达到阈值,触发保护机制。
6.6.4 授权规则
链接:授权规则
6.7 使用@SentinelResource注解
前面的Sentinel
常用规则主要是用Sentinel
控制面板上的一些规则、参数去配置限流保护
还有一种能够实现定制化保护,实现更细粒度的规则保护,那就是在代码层面用@SentinelResource
定制自己的流控规则。
说人话,
@SentinelResource
可以贴在接口上面,指定接口限流时做的操作(比如自定义返回的提示内容),这样就做到了每个接口都能够有自己的限流提示信息。而不是返回Sentinel
默认的Block By Sentinel(flow limiting)
。
6.7.1 blockHandler 属性-指定限制响应方法
6.7.2 热点规则
链接:热点规则
6.7.3 fallback 属性-指定业务异常响应方法
fallback
属性和上面的blockHandler
属性都是用来指定处理方法的,它指定的是业务代出现异常后的处理方法,当业务报出异常就会进入指定的方法响应请求。
@RequestMapping("/fallBackTest")
@SentinelResource(value = "fallBackTest", fallback = "fallBackHandler")
public String fallBackTest(String param) {
int i = 1 / 0;
return "return from fallBackTest";
}
异常响应方法
public String fallBackHandler(String param, BlockException blockException) {
return "return from customfallBackHandler" + RandomUtils.nextInt();
}
因为有int i = 1 / 0
,所以接口必报算术异常,进入fallBackHandler()
方法响应请求。
如果没有生效有可能是版本问题,
1.6.0
之前的版本不能针对业务异常进行处理。
blockHandler
和fallback
属性是可以一起用的,当达到阈值时直接进入blockHandler
指定的限制响应方法;当没有达到阈值&业务出现异常时,直接执行fallback
指定的异常响应方法。
如果有想要忽略的异常不想交由
blockHandler
指定的限制响应方法处理,可以用exceptionsToIgnore
属性指定。
如:@SentinelResource(value = "fallBackTest", fallback = "fallBackHandler",exceptionsToIgnore = {RuntimeException.class})
,表示忽略RuntimeException.class
类型的异常。
6.7.4 代码优化
在上面对于blockHandler
和fallback
属性的使用,其指定的方法都放在了Controller
中,这样会显得非常凌乱
这时候可以使用另外两个对应的属性fallbackClass
和blockHandlerClass
来优化代码结构。
首先定义fallbackClass
指定的异常响应类:
public class FallBackHandler {
public static String fallBackHandler(String param, BlockException blockException) {
return "return from customfallBackHandler" + RandomUtils.nextInt();
}
}
注意:方法必须用
static
修饰。
同理定义限制响应类
public class CustomBlockHandler {
public static String customBlockHandler(String param, BlockException blockException) {
return "return from customBlockHandler" + RandomUtils.nextInt();
}
}
绑定资源,指定响应类,指定响应方法名
@RequestMapping("/test")
@SentinelResource(value = "fallBackTest",
blockHandlerClass = {CustomBlockHandler.class},blockHandler = "customBlockHandler",
fallbackClass = {FallBackHandler.class},fallback = "fallBackHandler")
public String fallBackTest(String param) {
int i = 1 / 0;
return "return from fallBackTest";
}
6.8 Sentinel持久化
Sentinel
支持多种持久化方案:
- 存储到文件
- 使用
Redis
存储 - 使用
Nacos
存储 - 使用
Zookeeper
存储 - 使用
Apollo
存储
因为Nacos
与Sentinel
同属于SpringCloudAlibaba
,因此我选择用nacos
。
配置nacos数据源:
加入nacos
数据源依赖
<!-- sentinel nacos 数据源 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
6.8.1 持久化流控规则
- 增加数据源配置
修改bootstrap.yml
配置文件(一下只是修改部分的配置)
spring:
application:
name: sentinel-consumer # 应用名
cloud:
sentinel:
transport:
port: 8719 # 启动一个端口为8719的 Http Server 与仪表盘进行交互,
dashboard: 127.0.0.1:8051 # 仪表盘
datasource: # 新增
datasource1: # 新增 自定义数据源名字
nacos: # 新增 数据源类型
server-addr: 124.221.89.200:8848 # 新增 nacos 服务地址
dataId: sentinel-consumer-datasource1 # 新增 对应nacos上配置的ID
groupId: DEFAULT_GROUP # 新增 对应nacos上配置所在的组
data-tupe: json # 新增 对应nacos上配置的类型
rule-type: flow # 新增 flow 表示流控规则
- 在
nacos
上添加配置
[ { "resource":"/test", "limitApp":"default", "grade":1, "count":1, "strategy":0, "controlBehavior":0, "clusterMode":false } ]
说明:
resource
:资源名称
limitApp
:限制来源
grade
:阈值类型(0-线程数
、1-QPS
)
count
:阈值
strategy
:流控模式(直接、关联、链路)
controlBehavior
:流控效果(快速失败、Warm Up、排队等待)
clusterMode
:是否集群
对应的
Bean
类为com.alibaba.csp.sentinel.slots.block.flow.FlowRule
public class FlowRule extends AbstractRule { private int grade = 1; private double count; private int strategy = 0; private String refResource; private int controlBehavior = 0; private int warmUpPeriodSec = 10; private int maxQueueingTimeMs = 500; private boolean clusterMode; private ClusterFlowConfig clusterConfig; private TrafficShapingController controller; ... }
这样子无论是重启Sentinel
控制台还是重启应用服务
都不会丢失流控设置。
6.8.2 持久化降级规则
上面配置了一个流控规则的持久化库
现在配置一个降级规则的持久化库,因为已经导入依赖了,直接加配一个数据源即可
- 修改
bootstrap.yml
配置文件(一下只是修改部分)
spring:
application:
name: sentinel-consumer # 应用名
cloud:
sentinel:
transport:
port: 8719 # 启动一个端口为8719的 Http Server 与仪表盘进行交互,
dashboard: 127.0.0.1:8051 # 仪表盘
datasource:
datasource1:
nacos:
server-addr: 124.221.89.200:8848
dataId: sentinel-consumer-datasource1
groupId: DEFAULT_GROUP
data-tupe: json
rule-type: flow
datasource2: # 新增
nacos: # 新增
server-addr: 124.221.89.200:8848 # 新增
dataId: sentinel-consumer-datasource2 # 新增
groupId: DEFAULT_GROUP # 新增
data-tupe: json # 新增
rule-type: degrade # 新增 degrade 表示降级规则
- 在
nacos
上添加配置
[
{
"resource":"/test",
"limitApp":"default",
"grade":2,
"count":1,
"timeWindow":3
}
]
timeWindow
:时间窗口
这样降级数据源也配置好了
对应的
Bean
类为com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule
public class DegradeRule extends AbstractRule { private int grade = 0; private double count; private int timeWindow; private int minRequestAmount = 5; private double slowRatioThreshold = 1.0D; private int statIntervalMs = 1000; ... }
6.8.2 持久化系统规则
一样的,也是在bootstrap.yml
配置文件中新配置一个数据源
spring:
application:
name: sentinel-consumer # 应用名
cloud:
sentinel:
transport:
port: 8719 # 启动一个端口为8719的 Http Server 与仪表盘进行交互,
dashboard: 127.0.0.1:8051 # 仪表盘
datasource:
datasource1:
nacos:
server-addr: 124.221.89.200:8848
dataId: sentinel-consumer-datasource1
groupId: DEFAULT_GROUP
data-tupe: json
rule-type: flow
datasource2:
nacos:
server-addr: 124.221.89.200:8848
dataId: sentinel-consumer-datasource2
groupId: DEFAULT_GROUP
data-tupe: json
rule-type: degrade
datasource3: # 新增
nacos: # 新增
server-addr: 124.221.89.200:8848 # 新增
dataId: sentinel-consumer-datasource3 # 新增
groupId: DEFAULT_GROUP # 新增
data-tupe: json # 新增
rule-type: system # 新增 system 表示系统规则
nacos
创建对应配置
系统规则属性:
avgRt
:系统平均响应时间
highestCpuUsage
:CPU使用率
highestSystemLoad
:负载
maxThread
:最大业务线程数
qps
:每秒处理请求数
对应的
Bean
为com.alibaba.csp.sentinel.slots.system.SystemRule
public class SystemRule extends AbstractRule { private double highestSystemLoad = -1.0D; private double highestCpuUsage = -1.0D; private double qps = -1.0D; private long avgRt = -1L; private long maxThread = -1L; ... }
持久化注意事项:
Sentinel
的持久化相当于直接从数据源拉取配置创建规则,所以更改Nacos
上的配置Sentinel
规则会即时生效,重启也不会丢失。- 修改
Sentinel
上的配置而没有修改Nacos
数据源上的配置,重启会丢失,因为修改并不会自动同步到Nacos
上。