1、流控规则

image.png

1、基本介绍:

  • 资源名: 唯一名称,默认请求路径
  • 针对来源:Sentinel可以针对调用者进行限流,填写微服务名,默认default(不区分来源)
  • 阈值类型/单机阈值
    • QPS(每秒钟的请求数量):当调用该api的QPS达到阈值的时候,进行限流
    • 线程数:当调用该api的线程数达到阈值的时候,进行限流
  • 是否集群:不需要集群

image.png

2、流控模式:

(1)如何设置
设置有两种方式,第一种是在簇点链路中直接点击对那个接口进行流控
第二种方式是在设置流控规则
image.png

  • 直接(默认) api达到限流条件时,直接限流
    • 直接->快速失败—-系统默认的
    • 配置及说明
    • 测试

image.png

  • 关联 (当关联的资源达到阈值时,就限流自己)

当与A关联的资源B达到阈值后,就限流自己,B惹事,A挂了
image.png
image.png

  • 链路

多个请求调用同一个微服务

3、流控效果:

1、直接->快速失败(默认的流控处理)

直接失败,抛出异常(Blocked by Sentinel (flow limiting))
源码: image.png

2、预热(Warm up)

Warm up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,即预热/冷启动方式。
当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。
通过“冷启动”,让通过的流量缓慢增加,在一定时间内捉奸增加到阈值上线,给冷系统一个预热的时间,
避免冷系统压垮。

image.png

3、排队预热

匀速排队,让请求以均匀的速度通过,阈值类型必须设成QPS,否则无效。
设置含义:/testA每秒1次请求,超过的话就排队等待,等待的超时时间为20000毫秒
image.png

3、降级规则

1、基本介绍

image.png
这三个的组合,排列
降级策略
RT(平均响应时间,秒级)
平均响应时间超出阈值 且 在时间窗口内通过的请求>=5,两个条件同时满足后触发降级窗口期过后关闭断路器
RT最大4900
异常比例(秒级)
QPS>=5且异常比例(秒级统计)超过阈值时,触发降级;时间窗口结束后,关闭降级、
异常数(分钟)
异常数(分钟统计)超过阈值时,触发降级;时间窗口结束后,关闭降级。
image.png
Sentinel熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速
失败,避免影响到其它的资源而导致级联错误。

当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断

2、降级策略实战

1、RT

是什么
image.png
测试
image.png
image.png

2、异常比例

image.png
image.png

3、异常数

异常数:当资源近1分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若timeWindow小于60s,则结束熔断状态后仍可能再进入熔断状态。

时间窗口一定要大于等于60秒

image.png

异常数是按分钟统计的
image.png

4、热点规则

image.png

兜底方法

分为系统默认和客户自定义两种,
之前的case,限流出问题后,都是用sentinel系统默认的提示: Blocked by Sentinel(flow limiting).

我们能不能自定义?类似hstrix,某个方法出问题了,就找对应的兜底降级方法?

结论
从HystrixCommand到@SentinelResource

  1. @GetMapping("/testHotkey")
  2. @SentinelResource(value = "testHotkey",blockHandler = "deal_testHotKey")
  3. public String testHotkey(@RequestParam(value = "p1",required = false) String p1,
  4. @RequestParam(value = "p2",required = false)String p2){
  5. return "----------testHotKey";
  6. }
  7. public String deal_testHotKey(String p1 , String p2 , BlockException exception){
  8. return "------deal_testHotKeyo(╥﹏╥)o";//sentinel 系统默认的提示:Blocked by sentine
  9. }

image.png
image.png
方法testHotKey里面第一个参数只要QPS超过每秒1次,马上降级处理
image.png

参数例外项

普通:超过1秒钟一个后,达到阈值1后马上被限流

我们期望p1参数当为个特殊值后,特殊执行
image.png
image.png
前提条件:

@SentinelResource
处理的是Sentinel控制台配置的违规情况,有blockHandler方法配置的兜底处理

RuntimeException

int age=10/0,这个是java运行时报出的运行时异常RunTimeException , @SentinelResource不管

总结
@SentinelResource主管配置出错,运行出错该偶组异常走异常。

5、 系统规则(总控的功能)

是什么?

Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。

image.png

  • 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)

image.png
随便访问一个接口一秒超过1次
image.png

6、@SentinelResouce

1、按资源名称限流+后续处理

启动Nacos成功
启动Sentinel成功
配置流控规则
配置步骤
image.png
图形配置和规则

2、按照Url地址限流+后续处理

通过访问的URL来限流,会返回Sentinel自带默认的限流处理信息
业务类RateLimitController
访问一次
Sentinel控制台配置
测试

image.png
会返回Sentinel自带的结果

  1. @GetMapping("/byResource")
  2. @SentinelResource(value = "byResource",blockHandler = "handleException")
  3. public CommonResult byResource(){
  4. return new CommonResult(200,"按资源名称限流测试OK",new Payment(2020L,"serial001"));
  5. }
  6. public CommonResult handleException(BlockException exception){
  7. return new CommonResult(444,exception.getClass().getCanonicalName()+"\t 服务不可用");
  8. }
  9. @GetMapping("/rateLimit/byUrl")
  10. @SentinelResource(value = "byUrl")
  11. public CommonResult byUrl(){
  12. return new CommonResult(200,"按url限流测试ok",new Payment(2020L,"serial002"));
  13. }

没有兜底的就用自带的

上面兜底方案面临的问题

  1. 1、系统默认的,没有体现我们自己的业务要求
  2. 2、依照现有提交,我们自定义的处理方法又和业务代码耦合在一起,不直观。
  3. 3、每个业务方法都添加一个兜底的,那代码膨胀加剧。
  4. 4、全局统一的处理方法没有体现

3、客户自定义限流处理逻辑

1、创建CustomerBlockHandler类用于自定义限流处理逻辑

image.png

  1. public class CustomerBlockHandler {
  2. public static CommonResult handlerException(BlockException exception){
  3. return new CommonResult(200,"按客户自定义",new Payment(2020L,"serial003"));
  4. }
  5. public static CommonResult handlerException2(BlockException exception){
  6. return new CommonResult(200,"按客户自定义",new Payment(2020L,"serial003"));
  7. }
  8. }

2、自定义限流处理类-CustomerBlockHandler

3、RateLimitController

  1. // CustomerBlockHandler
  2. @GetMapping("/rateLimit/CustomerBlockHandler")
  3. @SentinelResource(value = "CustomerBlockHandler",blockHandlerClass = CustomerBlockHandler.class,
  4. blockHandler = "handlerException2")
  5. public CommonResult CustomerBlockHandler(){
  6. return new CommonResult(200,"按客户自定义",new Payment(2020L,"serial003"));
  7. }

4、启动微服务后先调用一次

image.png

5、Sentinel控制台配置

image.png

6、测试后我们自定义的出来了

image.png

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 逻辑中,而是会原样抛