Sentinel 是由阿里巴巴中间件团队开发的开源项目,是一种面向分布式微服务架构的轻量级高可用流量控制组件。
Sentinel 主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度帮助用户保护服务的稳定性。
Sentinel 主要由以下两个部分组成:
Sentinel 核心库不依赖 Sentinel Dashboard,但两者结合使用可以有效的提高效率,让 Sentinel 发挥它最大的作用。
微服务中的某服务故障,导致整个连链路中的所有微服务都不可用
解决雪崩问题的常见方式有四种:
下载好jar包后解压直接使用
通过CMD命令
java -jar sentinel-dashboard-1.8.1.jar
默认端口号8080,由于我的8080被使用,所以使用下面的命令更改端口号,并解压
java -Dserver.port=8123 -jar sentinel-dashboard-1.8.1.jar
解压成功通过端口号直接访问
在需要的微服务中添加依赖
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
在配置文件中指定sentinel地址
spring.cloud.sentinel.transport.dashboard=localhost:8123
重启微服务并测试
就是项目内的调用链路,链路中被监控的每个接口就是一个资源。默认情况下sentinel会监控SpringMVC的每一个端点(Endpoint),因此SpringMVC的每一个端点(Endpoint)就是调用链路中的一个资源
在添加限流规则时,点击高级选项,可以选择三种流控模式:
•直接:统计当前资源的请求,触发阈值时对当前资源直接限流,也是默认的模式•关联:统计与当前资源相关的另一个资源,触发阈值时,对当前资源限流•链路:统计从指定链路访问到本资源的请求,触发阈值时,对指定链路限流
结果只有五次通过
使用场景:比如用户支付时需要修改订单状态,同时用户要查询订单。查询和修改操作会争抢数据库锁,产生竞争。业务需求是有限支付和更新订单的业务,因此当修改订单业务触发阈值时,需要对查询订单业务限流。
限制谁的流量就操作谁,假如需要设定C达到阈值限制B的流量,就需要在B上添加流控规则。
开启测试后通过浏览器访问read接口,发现被限流
Sentinel默认只标记Controller中的方法为资源,如果要标记其它方法,需要利用@SentinelResource注解
创建两个controller层接口,调用同一个service层方法
添加此注解后,sentinel会将他也识别到
Sentinel默认会将Controller方法做context整合,导致链路模式的流控失效,需要修改application文件
使用压测工具进行测试
创建两个测试访问两个接口
流控效果是指请求达到流控阈值时应该采取的措施,包括三种:
当达到阈值时,请求会被直接拒绝。上面的例子用的都是快速失败,这里不再举例。
大白话来讲,刚开始把 阈值调低,不要让过多的请求访问服务器,导致冲垮服务器,先让服务器一点一点处理,再慢慢加量。经典的例子:一个好久没运动的人,你刚开始让他跑10圈,他可能会累死,但是你给他一个预热时间,比如 第一天跑 2圈,第三天跑 3 圈,第四天跑4圈,以此类推...
建立接口
添加流控模式
通过压测工具测试
可以看到刚开始放行的请求少,逐渐加多
通过sentinel的实时监控可以更直观看到,阈值逐渐加大,没有像山峰一样忽高忽低。
先进行测试在阐述原理
定义流控效果
定义测试
基于漏桶算法的排队等待模式
Sentinel排队等待只支持QPS在1000以下。
它的中心思想是,以固定的间隔时间让请求通过。当请求到来的时候,如果当前请求距离上个通过的请求通过的时间间隔不小于预设值,则让当前请求通过。否则,计算当前请求的预期通过时间,如果该请求的预期通过时间小于规则预设的 timeout 时间,则该请求会等待直到预设时间到来通过(排队等待处理);若预期的通过时间超出最大排队时长,则直接拒接这个请求。
代码逻辑
@1 计算请求通过的间隔时间
假如设置的阈值为count=100即每秒允许100个请求,每次通过一个请求acquireCount=1,套入公式costTime=10。即两次请求的时间间隔为10秒
@2 计算这次请求通过的预期时间=上次请求通过的时间+时间间隔
@3 当前时间大于预期时间,则允许通过并更新上次请求时间戳
@4 当前时间小于预期时间,则需要等待;计算需要等待的时间
@5 需要等待的时间大于超时时间则拒绝,默认超时时间为500毫秒
@6 再算一遍等待时间,算法跟第4步一样,并再次判断是否超过等待时间
@7 线程sleep等待时间后允许请求通过
我自己的理解:
我们给定等待时间为2秒,假如他每一秒能处理5个请求,200毫秒处理一个,那假如每一秒都会有11个请求进来,处理掉5个后,剩下的6个的都会排队,这时,时间来到下一秒,他继续处理上一秒未能处理掉的去排队的请求,这时又进来11个请求,由于上一秒的11个请求还没处理完,所以这一秒的11个请求会继续去排队,以此类推,但排队的队伍长度是我们定好的,我们定了2秒,因为他一秒处理五个,所以2秒能处理掉10个,也就是等待队列只能有10个排队的请求,但这个10是我们人为算出来的,我个人理解的是,程序并不是通过数量去测算的,而是通过时间,超过等待时间的会被直接拒绝,在上边的代码逻辑中提到了时间,这个我并是不是十分理解,我只能认为他每处理完一个请求,都会记录一个时间,然后还会计算出来一个处理一个请求大概需要多久,我这里假定是200毫秒,然后每进来一个请求,他会计算这个等待队列处理到这个新来的请求需要多长时间(怎么算的不理解),然后拿这个时间去跟我们规定的等待时间对比,超过了等待时间就拒绝掉这个请求,他只是拒绝了这个请求,并没有关闭这个服务端口,所以请求还是不断地进来,每进来一个他都会算时间是否等待会超时,而他200毫秒也会处理掉一个请求,一直到计算的等待时间不超时了,新请求就会排到等待队列中,他处理掉一个整个队伍都会往前移动一个,这就空出来一个位置,这就能进来一个新请求。也就是只要我处理完1个请求后,2秒内能处理到你的就会等待。(这个2秒是我们规定的等待时间)。
参考文章
Sentinel漏桶匀速限流https://blog.csdn.net/gaoliang1719/article/details/109567962?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2~default~CTRLIST~Rate-1-109567962-blog-118339191.pc_relevant_multi_platform_whitelistv4eslandingrelevant&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2~default~CTRLIST~Rate-1-109567962-blog-118339191.pc_relevant_multi_platform_whitelistv4eslandingrelevant&utm_relevant_index=1