Spring Cloud Alibaba Sentinel 熔断降级策略实战

2022-11-22 16:39:39 浏览数 (1)

书接前文:服务容错的必要性与Spring Cloud Alibaba Sentinel 限流配置实战 ,本文主要介绍 Sentinel 的熔断降级。

前置:什么是熔断降级

简而言之,熔断降级是保证微服务架构系统不会因为某个调用不稳定导致整个系统雪崩的一种手段。

现在的微服务系统大多是分布式的,一般由很多微服务项目组成。一个微服务通常会调用其他模块,比如第三方 API ,数据库, 亦或者是另外的一个远程服务。

比如,支付服务,首先需要查询商品的价格而去查询数据库,同时还需要调用支付宝、微信或银联支付提供的三方API。然而,我们并不能完全相信依赖的服务的稳定性,如果调用的其他服务响应时间变长了,那么我们调用者本身的响应时间就会变长,久而久之,线程堆积,终究会导致资源耗尽,自身服务将会变得不可用!

那如何破?我们需要对不稳定的 弱依赖服务调用 进行 「熔断降级」 ,暂时切断不稳定的调用,避免局部不稳定因素导致整体的雪崩。

实战:配置 Sentinel 熔断策略

根据前面我们配置 限流 规则的套路,此处还是从 Sentinel 的控制台切入配置,先来看一下,配置熔断策略的界面:

image-20220730105158216

image-20220730105219005

来看一下熔断规则的这些字段:

  • 资源名 :唯一名称,默认请求路径。
  • 熔断策略 :包括 「慢调用比例」「异常比例」「异常数」
  • 最大RT :RT 就是响应时间,这里设置 「最大响应时间」 。熔断策略配置为 慢调用比例 时,必须设置该字段,用来确定哪些请求是慢调用。
  • 比例阈值 :配置 慢调用比例 时该值为慢调用占所有请求的比例上限;配置 异常比例 时为请求异常所占比例的上限。取值范围:0 ~ 1。
  • 异常数 :就是请求的异常数量。注意:Sentinel 中异常降级的统计是仅针对 「业务异常」 ,Sentinel 进行降级时本身的异常(BlockException)是不生效的。
  • 熔断时长 :熔断经过该值后恢复到 「HALF-OPEN」 状态。HALF-OPEN 状态:熔断后经过熔断时长后的第一个请求成功而没有错误则恢复正常结束熔断,否则继续熔断。
  • 最小请求数 :请求数目大于该值时才会根据配置的熔断策略进行降级。
  • 统计时长 :应该和上面几个字段联合起来理解:当 单位统计时长 内满足请求数目大于 最小请求数 时才会根据配置的熔断策略进行降级。

举个例子,做如下配置:

该配置将要达到的效果是:「1秒(1000ms)内达到10个请求以上,当响应时长超过0.3秒的请求数量大于1(10 * 0.1)个的时候进行熔断,熔断10秒后变成 Half Open 状态,即10秒后的第一个请求若没有问题则恢复正常,否则继续熔断。」 这是一个 慢调用比例 的熔断策略。

下面就以这个例子开始,进行实际操作看下效果。

慢调用比例

根据上面的例子,最大RT为300ms,让程序随机睡 0 到 1000 ms,超过300ms的就是慢调用。

首先写一个接口(资源)演示慢调用比例策略:

代码语言:javascript复制
@GetMapping("/testSlowRate")
public String testSlowRate() {    
    //随机睡眠毫秒数
    int sleepSeconds = (int) (Math.random() * 1000);
    try {
        TimeUnit.MILLISECONDS.sleep(sleepSeconds);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "testSlowRate success!";
}

JMeter 来测试,1秒内发10个请求到 /testSlowRate ,循环发送:

JMeter 在跑的时候,我们可以预测到应该会限流,因为只要有一个请求的睡眠时间超过300ms,就会熔断:

image-20220730155238408

红色的都是被限流的请求,正常的请求(响应时间低于300ms请求的比例小于0.1):

10秒之后,我们从浏览器访问一下接口:

请求资源恢复正常了,因为我一次只发了一个请求没有到熔断的条件。

异常比例

根据前面的解释,配置 异常比例 熔断策略时,需配置 比例阈值 ,如下的配置策略意为:

「当 1s 内发送请求数大于5并且请求异常的比例大于0.2的时候,进行熔断,10s 后再次请求,若请求正常则恢复,否则继续熔断。」 下面来验证一下。

「1.」 写一个接口作为请求资源,模拟程序异常

代码语言:javascript复制
@GetMapping("/testExceptionRate")
public String testExceptionRate(Integer id) {
    if (id == 0) {
        throw new RuntimeException("id 不能等于0!");
    }
    return "testExceptionRate success!";
}

只要传入的 id 为 0,就算一个请求异常。

「2.」 JMeter 下1s发10个请求 http://localhost:7072/testExceptionRate?id=0 必定全部异常,同时满足 最小请求数比例阈值 的熔断规则,请求必然熔断:

「3.」 JMeter 正在运行的时候,这时访问接口传入一个id非0的数据应该也是熔断的,因为有请求一直异常,此时还处于熔断状态:

「4.」 10秒后,仍然访问,传入id=0是请求异常,但是只发了一个请求,不满足熔断条件,所以请求不回熔断:

异常数

异常数的策略就比较简单了,单位请求时长内达到最小请求数,并且异常的请求数量大于配置的异常的时候就进行熔断。

接口资源和上面的异常比例几乎一样:

代码语言:javascript复制
@GetMapping("/testException")
public String testException(Integer id) {
    if (id == 0) {
        throw new RuntimeException("id 不能等于0!");
    }
    return "testException success!";
}

JMeter 配置也是一样,1秒内发10个请求都是异常(id=0),就达到了异常数,接下来的请求将会被熔断:

同理,经过熔断时长 10s 后,再次请求将恢复正常:

小结:学废了吗?

  • 微服务架构中存在多个服务之间的请求调用,形成了一个复杂的调用链路,如果调用连路上任何一个环节出现问题将会导致整个系统不可用,因此需要对请求不稳定的调用进行 「熔断降级」
  • Sentinel 的熔断策略包括 慢调用比例异常比例异常数
  • 慢调用比例 :当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。
  • 异常比例 :当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。
  • 异常数 :当单位统计时长内的异常数目超过阈值之后会自动进行熔断。
  • 经过 熔断时长 后,会进入 HALF-OPEN 状态,即看接下来的第一个请求是否成功没有错误,如果成功则结束熔断,否则继续熔断。

0 人点赞