目录
一、降级规则
(一)官网
(二)基本介绍
(三)降级策略实战
二、热点key限流
(一)基本介绍
(二)官网
(三)测试
(四)参数例外项
三、系统规则(了解即可)
四、@SentinelResource
(一)按资源名称限流+后续处理
(二)按照Url地址限流+后续处理
(三)更多注解属性说明
一、降级规则
(一)官网
熔断降级 · alibaba/Sentinel Wiki · GitHub
(二)基本介绍
RT(平均响应时间,秒级)
平均响应时间 超出阈值 且 在时间窗口内通过的请求>=5,两个条件同时满足后触发降级
窗口期过后关闭断路器
RT最大4900(更大的需要通过-Dcsp.sentinel.statistic.max.rt=XXXX才能生效)
异常比例(秒级)
QPS >= 5 且异常比例(秒级统计)超过阈值时,触发降级;时间窗口结束后,关闭降级
异常数(分钟级)
异常数(分钟统计)超过阈值时,触发降级;时间窗口结束后,关闭降级
进一步说明
Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,
让请求快速失败,避免影响到其它的资源而导致级联错误。
当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出 DegradeException)。
Sentinel的断路器是没有半开状态的。半开的状态系统自动去检测是否请求有异常,没有异常就关闭断路器恢复使用,有异常则继续打开断路器不可用,具体可以参考Hystrix
(三)降级策略实战
1、RT
代码
@GetMapping("/testD")
public String testD()
{
//暂停几秒钟线程
try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
log.info("testD 测试RT");
return "------testD";
}
配置
jmeter压测
结论
按照上述配置,
永远一秒钟打进来10个线程(大于5个了)调用testD,我们希望200毫秒处理完本次任务,
如果超过200毫秒还没处理完,在未来1秒钟的时间窗口内,断路器打开(保险丝跳闸)微服务不可用,保险丝跳闸断电了
后续我停止jmeter,没有这么大的访问量了,断路器关闭(保险丝恢复),微服务恢复OK
2、异常比例
代码
@GetMapping("/testD")
public String testD()
{
log.info("testD 测试RT");
int age = 10/0;
return "------testD";
}
配置
指的是一秒内打进来的请求中异常比例不超过0.2就不开启断路器
jmeter压测
结论
按照上述配置,
单独访问一次,必然来一次报错一次(int age = 10/0),调一次错一次;
开启jmeter后,直接高并发发送请求,多次调用达到我们的配置条件了。
断路器开启(保险丝跳闸),微服务不可用了,不再报错error而是服务降级了。
3、异常数
意思是我们设置的时间窗口最好大于60s
代码
@GetMapping("/testE")
public String testE()
{
log.info("testE 测试异常比例");
int age = 10/0;
return "------testE 测试异常比例";
}
配置
http://localhost:8401/testE,第一次访问绝对报错,因为除数不能为零,
我们看到error窗口,但是达到5次报错后,进入熔断后降级。
jmeter压测
测试
二、热点key限流
(一)基本介绍
何为热点
热点即经常访问的数据,很多时候我们希望统计或者限制某个热点数据中访问频次最高的TopN数据,并对其访问进行限流或者其它操作
(二)官网
https://github.com/alibaba/Sentinel/wiki/%E7%83%AD%E7%82%B9%E5%8F%82%E6%95%B0%E9%99%90%E6%B5%81
(三)测试
代码
blockHandler 即为兜底方法,如果没设置blockHandler出现的将是空白错误页white Error Page
注意:兜底的方法要写上原来方法带的所有参数+blockexception
@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey",blockHandler = "dealHandler_testHotKey")
public String testHotKey(@RequestParam(value = "p1",required = false) String p1,
@RequestParam(value = "p2",required = false) String p2){
return "------testHotKey";
}
public String dealHandler_testHotKey(String p1,String p2,BlockException exception)
{
return "-----dealHandler_testHotKey";
}
配置
限流模式只支持QPS模式,固定写死了。(这才叫热点)
@SentinelResource注解的方法参数索引,0代表第一个参数,1代表第二个参数,以此类推
单机阀值以及统计窗口时长表示在此窗口时间超过阀值就限流。
上面的抓图就是第一个参数有值的话,1秒的QPS为1,超过就限流,限流后调用dealHandler_testHotKey支持方法。
有p1参数的一秒钟内访问两次就会调用blockhandle方法(因为我们设置了一秒内次数1,超过就不行)
(四)参数例外项
如果我们期望p1参数当它是某个特殊值时,它的限流值和平时不一样,那就可以通过高级设置中的参数例外项来实现
这里我们设置当参数索引为0即p1的值为5时,他的限流阈值变成200,当p1不等于5的时候,阈值就是平常的1
前提条件:热点参数的注意点,参数必须是基本类型或者String
此时如果我们在业务代码中报出异常错误,会不会走blockhandler的兜底方法呢,我们发现并不会,而是报了空白页错误
总结:
@SentinelResource
处理的是Sentinel控制台配置的违规情况,有blockHandler方法配置的兜底处理;
RuntimeException
int age = 10/0,这个是java运行时报出的运行时异常RunTimeException,@SentinelResource不管
@SentinelResource主管配置出错,运行出错该走异常走异常
同时我们可以看到@sentinelResource 有一个fallback属性,这也许就是业务代码出现异常走的方法了,我们后面再讲。
@SentinelResource(value = "testhotkey", blockHandler = "deal_hotkey",fallback = )
三、系统规则(了解即可)
官网:系统自适应限流 · alibaba/Sentinel Wiki · GitHub
各项参数说明
配置全局QPS,指的是当系统中单台机器上的所有入口流量达到100后触发系统保护
四、@SentinelResource
(一)按资源名称限流+后续处理
即表示1秒钟内查询次数大于1,就跑到我们自定义的处流,限流 。
(二)按照Url地址限流+后续处理
通过访问的URL来限流,我们发现配置了handler方法也没有效果
@GetMapping("/rateLimit/byUrl")
@SentinelResource(value = "byUrl", blockHandler = "handleException2")
public CommonResult byUrl()
{
return new CommonResult(200,"按url限流测试OK",new Payment(2020L,"serial002"));
}
public CommonResult handleException2(BlockException exception)
{
return new CommonResult(444,exception.getClass().getCanonicalName()+"\t 服务不可用");
}
即会返回Sentinel自带默认的限流处理信息,
那么应该如何设置blockhandler呢?
①创建CustomerBlockHandler类用于自定义限流处理逻辑
public class CustomerBlockHandler
{
public static CommonResult handleException(BlockException exception){
return new CommonResult(2020,"自定义的限流处理信息......CustomerBlockHandler");
}
}
/**
* 自定义通用的限流处理逻辑,
blockHandlerClass = CustomerBlockHandler.class
blockHandler = handleException2
上述配置:找CustomerBlockHandler类里的handleException2方法进行兜底处理
*/
/**
* 自定义通用的限流处理逻辑
*/
@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler",
blockHandlerClass = CustomerBlockHandler.class, blockHandler = "handleException")
public CommonResult customerBlockHandler()
{
return new CommonResult(200,"按客户自定义限流处理逻辑");
}
即Sentinel会去找blockhandlerClass中的类寻找blockhander方法作为兜底方法
总结:
sentinel是根据@SentinelResource中的value值默认作为规则匹配的,所以以路径做流控规则,兜底方法不会生效
(三)更多注解属性说明
1、SphU定义资源
2、Tracer定义统计
3、ContextUtil定义了上下文