1 Sentinel简介
Sentinel是阿里开源的项目,提供了流量控制、熔断降级、系统负载保护等多个维度来保障服务之间的稳定性。
2 入门案例
下载sentinel和nacos后本地启动
2.1 maven配置
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
2.2 配置文件
spring:
application:
name: nacos-pay-consumer
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
dashboard: localhost:8080
port: 8719 # 假如被占用会从8719递增寻找
2.3 测试代码
@GetMapping("/test-sentinel")
public String testSentinel(Long id) {
if (id <= 0) {
throw new RuntimeException("id is invalid, " + id);
}
return "testSentinel";
}
访问
查看sentinel控制台
2.4 SentinelResource配置
blockHandler:触发sentinel规则限制后的兜底方法,默认从本类中寻找
blockHandlerClass:触发sentinel规则限制后的兜底类
fallback:运行时异常后的兜底方法, 默认从本类中寻找
fallbackClass:运行时异常后的兜底类
exceptionsToIgnore:忽略的异常,该异常不会被blockHandler和fallback捕获
3 流控规则
3.1 QPS限制
这里配置每秒钟访问一次,超过的话会直接报错
3.2 线程数限制
这里配置每次最多一个线程访问。
模拟高并发场景,测试代码如下
@GetMapping("/thread-limit")
public String threadLimit() throws InterruptedException {
Thread.sleep(1000);
return "ok";
}
快速访问后会发生限流
3.3 流控模式
3.3.1 直接流控模式
直接流控就是对本资源自己的限制,上面已经演示过
3.3.2 关联限制模式
当关联资源达到阈值后就限制自己。
满足下面条件可以使用关联模式:
- 两个有竞争关系的资源
- 一个优先级较高,一个优先级较低
比如用户支付时需要修改订单状态,同时用户要查询订单。查询和修改操作会争抢数据库锁,产生竞争。业务需求是有限支付和更新订单的业务,因此当修改订单业务触发阈值时,需要对查询订单业务限流。
3.3.3 链路流控模式
统计从指定链路访问到本资源的请求,触发阈值时,对指定上游链路限流。
针对资源resource,上游有两个链路,route1、route2,当访问达到阈值时对route1做限流
3.4 流控效果
3.4.1 快速失败
如上演示,直接提示
Blocked by Sentinel (flow limiting)
3.4.2 Warm Up(预热)
当流量突然增大的时候,我们常常会希望系统从空闲状态到繁忙状态的切换的时间长一些。即如果系统在此之前长期处于空闲的状态,我们希望处理请求的数量是缓步的增多,经过预期的时间以后,到达系统处理请求个数的最大值。Warm Up(冷启动,预热)模式就是为了实现这个目的的。
配置参数:coldFactor,默认值为3
QPS从 (threshold / coldFactor) 开始,经过多长时间逐渐上升至设定的QPS阈值
比如我们希望QPS从3开始,经过5秒上升到9,做如下配置
应用场景:如秒杀系统在开启瞬间,会有很多流量上来,很可能把系统打死,预热方式就是为了保护系统,可慢慢的把流量放进来,慢慢的把阈值增长到设置的阈值。
3.4.3 排队等待
匀速排队(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。阈值必须设置为QPS。
这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求。
4降级规则
Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如:调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其他的资源而导致级联错误。
4.1 RT(平均响应时间)
当资源的响应时间超过最大RT(以ms为单位,最大RT即最大响应时间)之后,且1s内持续进入5个请求(最小请求数)则会触发降级。窗口期过后关闭断路器
RT最大4900,更大需要配置-Dcsp.sentinel.statistic.max.rt=xxx
4.2 异常比例
当资源的每秒请求量>=5,且每秒异常比例超过阈值时,在接下来的时间窗口期内该方法调用会熔断
4.3 异常数
当资源近1分钟的异常数目超过阈值(异常数)之后会进行服务降级。注意由于统计时间窗口是分钟级别的,若熔断时长小于60s,则结束熔断状态后仍可能再次进入熔断状态。
5 热点规则
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。
热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
Sentinel 利用 LRU 策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。
使用热单参数限流式不能使用资源路径,必须要使用资源名的方式。
5.1 入门案例
- 测试代码
@GetMapping("/hot-key")
@SentinelResource(value = "hotKey", blockHandler = "hotKeyBlockHandler")
public String hotKey(@RequestParam(required = false) String p) {
return "hotKey";
}
public String hotKeyBlockHandler(String p) {
return "hotKeyBlockHandler";
}
- 热点配置
这里针对hotKey方法,第一个参数访问QPS限制为1
添加参数频繁访问后会进入blockHandler指定的方法
5.2 细粒度控制
如果参数值为a,QPS限制为5,其他参数限制为1
6 配置持久化
服务重启后,sentinel上的配置规则会清空。这里把配置持久化到nacos
6.1 修改配置文件
spring:
application:
name: nacos-pay-consumer
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
dashboard: localhost:8080
port: 8719 # 假如被占用会从8719递增寻找
datasource:
ds1:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow
6.2 nacos添加配置
[
{
"resource": "hotKey",
"limitApp": "default",
"grade": 1,
"count": 5,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
个人感觉这样的配置不是很方便,最好可以在sentinel上配置好后及时同步nacos