1、流控规则
1、基本介绍:
- 资源名: 唯一名称,默认请求路径
- 针对来源:Sentinel可以针对调用者进行限流,填写微服务名,默认default(不区分来源)
- 阈值类型/单机阈值
- QPS(每秒钟的请求数量):当调用该api的QPS达到阈值的时候,进行限流
- 线程数:当调用该api的线程数达到阈值的时候,进行限流
- 是否集群:不需要集群
2、流控模式:
(1)如何设置
设置有两种方式,第一种是在簇点链路中直接点击对那个接口进行流控
第二种方式是在设置流控规则
- 直接(默认) api达到限流条件时,直接限流
- 直接->快速失败—-系统默认的
- 配置及说明
- 测试
- 关联 (当关联的资源达到阈值时,就限流自己)
当与A关联的资源B达到阈值后,就限流自己,B惹事,A挂了
- 链路
多个请求调用同一个微服务
3、流控效果:
1、直接->快速失败(默认的流控处理)
直接失败,抛出异常(Blocked by Sentinel (flow limiting))
源码:
2、预热(Warm up)
Warm up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,即预热/冷启动方式。
当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。
通过“冷启动”,让通过的流量缓慢增加,在一定时间内捉奸增加到阈值上线,给冷系统一个预热的时间,
避免冷系统压垮。
3、排队预热
匀速排队,让请求以均匀的速度通过,阈值类型必须设成QPS,否则无效。
设置含义:/testA每秒1次请求,超过的话就排队等待,等待的超时时间为20000毫秒
3、降级规则
1、基本介绍
这三个的组合,排列
降级策略
RT(平均响应时间,秒级)
平均响应时间超出阈值 且 在时间窗口内通过的请求>=5,两个条件同时满足后触发降级窗口期过后关闭断路器
RT最大4900
异常比例(秒级)
QPS>=5且异常比例(秒级统计)超过阈值时,触发降级;时间窗口结束后,关闭降级、
异常数(分钟)
异常数(分钟统计)超过阈值时,触发降级;时间窗口结束后,关闭降级。
Sentinel熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速
失败,避免影响到其它的资源而导致级联错误。
当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断
2、降级策略实战
1、RT
2、异常比例
3、异常数
异常数:当资源近1分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若timeWindow小于60s,则结束熔断状态后仍可能再进入熔断状态。
时间窗口一定要大于等于60秒
4、热点规则
兜底方法
分为系统默认和客户自定义两种,
之前的case,限流出问题后,都是用sentinel系统默认的提示: Blocked by Sentinel(flow limiting).
我们能不能自定义?类似hstrix,某个方法出问题了,就找对应的兜底降级方法?
结论
从HystrixCommand到@SentinelResource
@GetMapping("/testHotkey")
@SentinelResource(value = "testHotkey",blockHandler = "deal_testHotKey")
public String testHotkey(@RequestParam(value = "p1",required = false) String p1,
@RequestParam(value = "p2",required = false)String p2){
return "----------testHotKey";
}
public String deal_testHotKey(String p1 , String p2 , BlockException exception){
return "------deal_testHotKeyo(╥﹏╥)o";//sentinel 系统默认的提示:Blocked by sentine
}
方法testHotKey里面第一个参数只要QPS超过每秒1次,马上降级处理
参数例外项
普通:超过1秒钟一个后,达到阈值1后马上被限流
我们期望p1参数当为个特殊值后,特殊执行
前提条件:
@SentinelResource
处理的是Sentinel控制台配置的违规情况,有blockHandler方法配置的兜底处理
RuntimeException
int age=10/0,这个是java运行时报出的运行时异常RunTimeException , @SentinelResource不管
总结
@SentinelResource主管配置出错,运行出错该偶组异常走异常。
5、 系统规则(总控的功能)
是什么?
Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
- Load 自适应(仅对 Linux/Unix-like 机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的
maxQps * minRt
估算得出。设定参考值一般是CPU cores * 2.5
。 - CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。
- 平均 RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
- 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
- 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
设置总的入口(设置全局QPS)
随便访问一个接口一秒超过1次
6、@SentinelResouce
1、按资源名称限流+后续处理
启动Nacos成功
启动Sentinel成功
配置流控规则
配置步骤
图形配置和规则
2、按照Url地址限流+后续处理
通过访问的URL来限流,会返回Sentinel自带默认的限流处理信息
业务类RateLimitController
访问一次
Sentinel控制台配置
测试
会返回Sentinel自带的结果
@GetMapping("/byResource")
@SentinelResource(value = "byResource",blockHandler = "handleException")
public CommonResult byResource(){
return new CommonResult(200,"按资源名称限流测试OK",new Payment(2020L,"serial001"));
}
public CommonResult handleException(BlockException exception){
return new CommonResult(444,exception.getClass().getCanonicalName()+"\t 服务不可用");
}
@GetMapping("/rateLimit/byUrl")
@SentinelResource(value = "byUrl")
public CommonResult byUrl(){
return new CommonResult(200,"按url限流测试ok",new Payment(2020L,"serial002"));
}
没有兜底的就用自带的
上面兜底方案面临的问题
1、系统默认的,没有体现我们自己的业务要求
2、依照现有提交,我们自定义的处理方法又和业务代码耦合在一起,不直观。
3、每个业务方法都添加一个兜底的,那代码膨胀加剧。
4、全局统一的处理方法没有体现
3、客户自定义限流处理逻辑
1、创建CustomerBlockHandler类用于自定义限流处理逻辑
public class CustomerBlockHandler {
public static CommonResult handlerException(BlockException exception){
return new CommonResult(200,"按客户自定义",new Payment(2020L,"serial003"));
}
public static CommonResult handlerException2(BlockException exception){
return new CommonResult(200,"按客户自定义",new Payment(2020L,"serial003"));
}
}
2、自定义限流处理类-CustomerBlockHandler
3、RateLimitController
// CustomerBlockHandler
@GetMapping("/rateLimit/CustomerBlockHandler")
@SentinelResource(value = "CustomerBlockHandler",blockHandlerClass = CustomerBlockHandler.class,
blockHandler = "handlerException2")
public CommonResult CustomerBlockHandler(){
return new CommonResult(200,"按客户自定义",new Payment(2020L,"serial003"));
}
4、启动微服务后先调用一次
5、Sentinel控制台配置
6、测试后我们自定义的出来了
7、进一步说明
value:资源名称,必需项(不能为空)
entryType:entry类型,可选项(默认为 EntryType.OUT)
fallback:fallback函数名称,可选项,用于在抛出异常的时候提供 fallback处理逻辑。fallback函数可以针对所有类型的异常(除了exceptionsToIgnore里面排除掉的异常类型)进行处理。fallback函数签名和位置要求: 返回值类型必须与原函数返回值类型一致;方法参数列表需要和原函数一致,或者可以额外多一个 Throwable类型的参数用于接收对应的异常。
fallback函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass为对应的类的 Class 对象,注意对应的函数必需为 static函数,否则无法解析。 defaultFallback(since 1.6.0):默认的 fallback函数名称,可选项,通常用于通用的 fallback逻辑(即可以用于很多服务或方法)。默认 fallback函数可以针对所有类型的异常(除了exceptionsToIgnore里面排除掉的异常类型)进行处理。若同时配置了 fallback和 defaultFallback,则只有 fallback会生效。defaultFallback函数签名要求:返回值类型必须与原函数返回值类型一致;
方法参数列表需要为空,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
defaultFallback函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
exceptionsToIgnore(since 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛