Sentinel的初步学习(2)https://blog.csdn.net/BinXNoob/article/details/106432883
Sentinel实现熔断限流》》》》》Hystrix
https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D
下载地址:https://github.com/alibaba/Sentinel/releases
下载完成后,确保jdk是1.8及其以上,8080端口没有被占用
进入cmd,输入 java -jar sentinel-dashboard-1.7.2.jar
如图:
出现这个界面就是启动成功
再去访问http://localhost:8080/ , 账号密码均是sentinel
就可以进入sentinel控制平台
需要引入sentinel的依赖以及后续持久化依赖
<dependency>
<groupId>com.xwb.springcloudgroupId>
<artifactId>cloud-api-commonsartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cspgroupId>
<artifactId>sentinel-datasource-nacosartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
启动8401端口,这时在sentinel的控制台中并没有看到我们的8401端口的信息
这是sentinel是懒加载的原因
我们需要先访问8401端口才可以
现在可以对我们8401进行实时监控
我们现在只是拿着我们的rest地址进行控制,也就是资源名
设置好之后,访问8401/TestA连接
在一秒内多次点击出现以下情况
表示1s内只允许查询1次,若是超过,直接快速失败,默认报错
这里我们应该类似一个fallback的兜底调用方法
当关联的资源达到阈值时, 就限流自己
若A关联的资源B达到阈值,就限流A
我们在sentinel的控制台设置A关联上B
进入collection设置
启动并访问A,发现A出现报错
阈值的冷启动(clodFactory)的默认值是3,需要经过预热时长后才会到达阈值
官方说明https://github.com/alibaba/Sentinel/wiki/%E9%99%90%E6%B5%81—%E5%86%B7%E5%90%AF%E5%8A%A8
我们启动sentinel控制台
进行设置
设置完成后
默认公式是冷启动时长3s
那么预热时间就是10/3+5,也就是一开始的阈值是3,经过5s后才慢慢恢复到10
我们访问TestB请求
保持一个速率刷新,一开始会报错,宕机
后面逐渐恢复正常
也就是,一个保护机制,在开启服务时,为了保护不被流量一次性过多进入。会慢慢把流量一点点放进来,逐渐增长到阈值
匀速排队,让请求以均匀的速度通过,阈值类型要设置成QPS,否则无效
/testA 每秒一次请求,超过的话排队等待,等待超时时间为20000毫秒
用于处理间隔性的突发流量
利用postman设置10个线程,1秒发送10个线程
出现以下情况
2020-04-29 15:45:55.853 INFO 14188 --- [nio-8401-exec-4] c.x.s.controller.SentinelController : http-nio-8401-exec-4 =======AAAAA
2020-04-29 15:45:56.879 INFO 14188 --- [nio-8401-exec-5] c.x.s.controller.SentinelController : http-nio-8401-exec-5 =======AAAAA
2020-04-29 15:45:57.915 INFO 14188 --- [nio-8401-exec-6] c.x.s.controller.SentinelController : http-nio-8401-exec-6 =======AAAAA
2020-04-29 15:45:58.931 INFO 14188 --- [nio-8401-exec-7] c.x.s.controller.SentinelController : http-nio-8401-exec-7 =======AAAAA
2020-04-29 15:45:59.952 INFO 14188 --- [nio-8401-exec-8] c.x.s.controller.SentinelController : http-nio-8401-exec-8 =======AAAAA
2020-04-29 15:46:00.968 INFO 14188 --- [nio-8401-exec-9] c.x.s.controller.SentinelController : http-nio-8401-exec-9 =======AAAAA
2020-04-29 15:46:01.987 INFO 14188 --- [io-8401-exec-10] c.x.s.controller.SentinelController : http-nio-8401-exec-10 =======AAAAA
2020-04-29 15:46:03.004 INFO 14188 --- [nio-8401-exec-2] c.x.s.controller.SentinelController : http-nio-8401-exec-2 =======AAAAA
2020-04-29 15:46:04.022 INFO 14188 --- [nio-8401-exec-1] c.x.s.controller.SentinelController : http-nio-8401-exec-1 =======AAAAA
2020-04-29 15:46:05.043 INFO 14188 --- [nio-8401-exec-3] c.x.s.controller.SentinelController : http-nio-8401-exec-3 =======AAAAA
这是因为队列等待设置成一秒1个
可以当作队列来理解,阀值为2,理解为同一时间读取队列中2个元素,若是一个元素处理完,读取下一个元素,剩下的元素如果在队列中等待的时间超过了timeout,就限流打回
https://github.com/alibaba/Sentinel/wiki/%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7
流控只是对流量大小进行控制,并不会对响应超时、异常的情况进行处理
RT (平均响应时间 )
平均响应时间 超出阈值 且 时间窗口内通过的请求 >=5 两个条件同时满足后触发降级
窗口期过后关闭断路器
RT最大 4900 (更大需要通过 -Dscp.sentinel.statistic.max.rt = XXXX 灿能生效)
异常比例 (秒级)
QPS >=5 且异常比例(秒级统计)超过阈值,触发降级,时间窗口结束后,关闭降级
异常数
异常数 (分钟统计)超过阈值,触发降级;时间窗借宿后, 关闭降级。
平均响应时间 (DEGRADEGRADERT):当 1s 内持续进入 5 个请求,对应时刻的平均响应时间(秒级)均超过阈值(count,以 ms 为单位),那么在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地熔断(抛出 DegradeException)。注意 Sentinel 默认统计的 RT 上限是 4900 ms,超出此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项 -Dcsp.sentinel.statistic.max.rt=xxx 来配置。
》》》》》》》》
1秒内持续5个请求,平均响应时间>阈值》》》》》》触发断路器,降级》》》》》时间窗口结束》》》》》关闭降级
我们编写一个test
在sentinel控制台进行降级修改
设置完成后,启动jmeter,设置压测
启动压测,访问请求端口TestD
异常比例 (DEGRADEGRADEEXCEPTION_RATIO):当资源的每秒请求量 >= 5,并且每秒异常总数占通过量的比值超过阈值(DegradeRule 中的 count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
》》》》》》》》》》》》
QPS>=5 && 异常比例(秒级统计)超过阈值》》》》》》触发降级,断路器打开》》》》》时间窗口期结束》》》》》关闭降级恢复正常
配置sentinel
配置jmeter
启动jmeter,我们发现浏览器出现sentinel默认报错
但是一旦我们关闭jmeter,他肯定页面百分百报错
为什么会报错???
因为,我们这个时候关闭了jmeter,她请求资源数自然降下来,当请求资源数小于sentinel默认的5之后,就不会进入降级,而是直接访问我们的请求,没了降级保护,自然而然报错。
开启了jmeter,直接高并发请求,多次调用到达了我们的配置条件,断路器自然而然开启,微服务自然而然不可用。便不会报错error,而是服务降级
异常数 (DEGRADEGRADEEXCEPTION_COUNT):当资源近 1 分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若 timeWindow 小于 60s,则结束熔断状态后仍可能再进入熔断状态。
时间窗口一定要要大于等于60秒
》》》》》》》》》
按照分钟统计,异常数超过阈值》》》》》》触发降级,断路器打开》》》》》时间窗口期结束》》》》关闭降级
设置sentinel,在70秒内,如果错误数超过5次,启动服务降级
访问请求地址E
由于我们的令其百分百报错,启动sentinel的异常数配置
刷新5次之后,触发降级
当我们等待时间窗口期过去之后,断路器关闭,关闭熔断降级,进入我们的微服务,这时服务再次报错
何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:
商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
Sentinel 利用 LRU 策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。热点参数限流支持集群模式。
通俗一点也即是,如果你传入的某个值(比如p1)的请求量达到一定的量,就对p1进行限流,其他值不限
我们先对sentinel控制台进行设置,设置限流第“0”位的参数
编写我们的请求代码,设置我们的兜底方法
/*
* 测试热点限流
* SentinelResource这里的value值名称唯一即可,对应sentinel控制台的资源名
* blockHandler,BlockException 是源码里的
* p1,p2是我们设置的热点值(也就是sentinel里面的参数索引,对应者0,1位)
* 自己设置兜底的方法deal_HotKey
* 而SentinelResource基本可以看成HystrixCommand
* */
@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey",blockHandler = "deal_HotKey")
public String testHotKey(@RequestParam(value = "p1",required = false)String p1,
@RequestParam(value = "p2",required = false)String p2
){
return "============testHotKey";
}
public String deal_HotKey(String p1, String p2, BlockException exception){
return "===========deal_HotKey======T_T";
}
启动8401端口,进行访问
当我们缓慢访问 0 位参数-----p1时
正常通过,
但是当我们一秒内多次访问,超过阈值1的时候,出现了限流
也就是将 @SentinelResource里面的这个参数去掉 blockHandler = "deal_HotKey"
我们访问量超过阈值后
出现以下的界面
这样子异常就打到了前台,对于用户的体验极差
我们这个兜底方法也可以近似的看作我们的异常捕获try/catch
先编辑好sentinel控制台
当我们访问p1=5的时候
我们没有达到阈值,不会跳转到我们的兜底方法
也就是说,当我们的p1=5的时候阈值达到200;当你为其他数值的时候阈值只有1(也可以理解为VIP用户和普通用户的区别)
这种异常不属于Block Exception
这是java运行的错误
属于RunTime Exception管理
运行后直接报错