基本介绍

进一步说明

Sentinel熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。

当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出 Degradeexception)。

Sentinel的断路器是没有半开状态的

半开的状态系统自动去检测是否请求有异常,没有异常就关闭断路器恢复使用,有异常则继续打开断路器不可用。具体可以参考Hystrix

复习Hystrix

1610803442912.png

1610803442946.png

降级策略实战(RT)

是什么

平均响应时间 (DEGRADE_GRADE_RT):当 1s 内持续进入 N 个请求,对应时刻的平均响应时间(秒级)均超过阈值(count,以 ms 为单位),那么在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地熔断(抛出 DegradeException)。注意 Sentinel 默认统计的 RT 上限是 4900 ms,超出此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项 -Dcsp.sentinel.statistic.max.rt=xxx 来配置。

1610803443012.png

测试

代码

  1. @GetMapping("/testC")
  2. public String testC() throws InterruptedException {
  3. TimeUnit.SECONDS.sleep(1);
  4. log.info("testC RT");
  5. return "------------testC";
  6. }

配置

这个配置是什么意思呢?

/testC资源,1s内连续5个请求,平均响应时间均需要在200ms内完成,如果都超过200ms,则会跳闸,在时间窗口1s内,是跳闸状态

1610803443039.png

jemeter压力测试

1610803443078.png

1610803443111.png

1610803443135.png

1610803443169.png

开始压测,然后访问 http://localhost:8401/testC

1610803443202.png

结论

永远一秒钟打进来10个线程(大于5个了)调用 testC,我们希望200ms处理完本次任务,

如果超过200毫秒还没处理完,在末来1秒钟的时间窗口内,断路器打开(保险丝跳闸)微服务不可用,保险丝跳闻断电了
后续我停止 jmeter,没有这么大的访问量了,断路器关闭(保险丝恢复),微服务恢复OK

1610803443230.png

降级策略实战 (异常比例 )

是什么

异常比例 (DEGRADE_GRADE_EXCEPTION_RATIO):当资源的每秒异常总数占通过量的比值超过阈值(DegradeRule 中的 count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。

1610803443278.png

QPS在1.6.2版本中是默认是多少呢

默认的QPS是2 , 可以自行配置

1610803443316.png

测试

代码

  1. @GetMapping("/testC")
  2. public String testC() throws InterruptedException {
  3. log.info("testC 异常比例");
  4. int i = 10 / 0;
  5. return "------------testC";
  6. }

配置

1610803443351.png

当请求达到设置的QPS,且异常比例超过 20% ,直接就服务降级

使用jemeter压测

1610803443392.png

先请求一次testC接口,会报by zero异常,当开启Jmeter压测后,再访问testF会快速失败,等关闭Jmeter后,再请求接口,又会报by zero异常

1610803443417.png

结论

单独访问一次,必然来一次报错一次( int i_=10/0),调一次错一次;

1610803443446.png

开启 Jemeter后,直接高并发发送请求,多次调用达到我们的配置条件了。

断路器开启(保险丝跳闸),微服务不可用了,不再报错 error而是服务降级了。

注意事项

异常不能用try….catch包裹,否则不能进行服务降级

  1. @GetMapping("/testC")
  2. public String testC() throws InterruptedException {
  3. log.info("testC 异常比例");
  4. try {
  5. int i = 10 / 0;
  6. } catch (Exception e) {
  7. e.printStackTrace();
  8. }
  9. return "------------testC";
  10. }

降级策略实战 (异常数 )

是什么

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

异常数是按分钟来统计的,所以时间窗口必须大于等于60s

1610803443496.png

上图就是表示,在一分钟内统计异常数超过阈值了,然后触发降级,打开断路器,等时间窗口结束,关闭降级

测试

代码

添加testE接口,接口中设置10/0,即模拟运行时异常

  1. @GetMapping("/testE")
  2. public String testE()
  3. {
  4. log.info(Thread.currentThread().getName()+"\t"+"...testE 测试 异常数");
  5. int i = 10/0;
  6. return "------testE 测试 异常数";
  7. }

配置

在sentinel-dashboard中设置testE的降级策略为异常数,异常数为5,时间窗口为70s

1610803443521.png

访问

请求接口testE,请求一次为by zero异常,请求两次也是报错,等请求到五次后就会出现服务降级,直接快速失败,等超过65s窗口期后,再请求testE,又会开始 异常数策略统计

1610803443550.png