Spring Cloud Alibaba一一熔断降级

熔断降级

       一个服务常常会调用别的模块,可能是另外的一个远程服务、数据库,或者第三方API等。例如,支付的时候,可能需要远程调用银联提供的API,查询摸个商品的价格,可能需要进行数据库查询,然而,这个被依赖服务的稳定性是不能保证的。如果依赖的服务出现了稳定的情况,请求的响应时间变长,那么调用服务的方法的响应时间也会变长,线程会产生堆积,最终可能耗尽业务自身的线程池,服务本身也变得不可用。

    现代微服务架构都是分布式的,由于非常多的服务组成。不同服务之间相互调用,组成复杂的调用链路。以上的问题在链路调用中会产生放大的效果。复杂链路上的某一环不稳定,就可能会层层级联,最终导致整个链路都不可用。因此我们需要对不稳定的若依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。熔断降级作为保护自身的手段,通常在客户端(调用端)进行配置。

1、熔断策略

  • 慢调用比例(平均响应时间):选择以慢调用比例作为阈值,需要设置允许的慢调用RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。档单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测回复状态(HALF-OPEN状态),若接下来的一个请求响应时间小于设置的慢调用RT则结束熔断,若大于设置的慢调用RT则会再次被熔断。
  • 异常比例(ERROR_RATIO):当单位统计时长(satIntervalMs)内请求数且大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是[0.0,1.0],代表0%-100%。
  • 异常数(ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。

2、平均响应时间

        平均响应时间超过5ms,后续的所有请求都会被熔断,熔断时间为5s,后续有一个请求响应时间小于5ms则结束熔断。

        案例:定义一个接口休眠1s后返回内容,用Jemeter 3s内发送10个请求发现全部处理了,设置降级规则后发现只处理了部分请求,其他请求被熔断了。

  3、异常比例

异常比例超过28%自动熔断,熔断时间为3s。

案例

int i = 0;
@GetMapping("/hel1o1")
public string hello1() (
     1++;
     //出现异常的概率为1/3
     if (i % 3 == @){
            throw new RuntimeException();
     }
     return "hello1";
}

4、异常数

这里需要注意的是异常数量是按照封装来计算的,异常比例和平均响应时间都是秒级别的。

热点参数限流

热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的Top K数据,并对其访问进行限制。

比如:

  •     商品ID为参数,统计一段时间内最常购买的商品ID并进行限制
  •     用户ID为参数,针对一段时间内频繁访问的用户ID进行限制

热点参数限流会统计传入参数中的热点参数,并根据配置限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热电参数的资源调用生效。

1、定义接口

@GetMapping("/hel1o3")
@SentinelResource("he11o3”) // 热点参数需要配置这个注解使用
public string hello3(string str1, string str2){
  return "hello3 -->"+str1+",-->"+str2;
}

2、设置限流规则

参数限流规则表示,hello3资源中第一个参数1s只能调用一次,超过阈值就限流。

3、限流后返回自定义兜底数据

@GetMapping("/hello3")
@SentinelResource(value ="hello3",blockHandler ="hello3Handler") // 热点参数需要配需这个注解使用
public string hello3(string str1, string str2) {
     return "hel1o3 -->"+str1+",-->"+str2;
}
// 这个方法只负责参数限流的异常,不会处理方法的运行时异常
// hel13Handler方法的参数和返回值要和原方法一直,BlockException用来接收方法的异常
public String hello3Handler(string str1, String str2, BlockException e){
    System.out.println("str1 = " + str1 + ", str2 = " + str2 + ", e = " + e);
    return"该资源已被限流”;
}

4、参数列外项

   热点参数还可以对不同的参数设置不同的qps的值。

当方法第一个参数值10的时候qps为5。

当方法第一个参数值为11的时候qps为10。

当方法第一个参数值为15的时候qps为15。

系统自适应限流

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

1、系统规则

    系统保护规则是从应用级别的入口流量进行控制,从单台机器的load、CPU使用率、平均RT、入口QPS和并发线程数等几个维度监控应用指标,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。

   系统保护规则是应用整体维度的,而不是资源维度的,并且**仅对入口流量生效**。入口流量指的是进入应用的流量(EntryType.IN),比如Web服务或Dubbo服务端接收的请求,都属于入口流量。

系统规则支持以下的模式:

  • Load自适应(仅对Linux/Unix-like机器生效):系统的load作为启发指标,进行自适应系统保护。当系统load超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才触发系统保护(BBR阶段)。系统容量由系统的maxQPS*minRt估算得出。设定参考值一般是CPU cores*2.5
  • CPU usage(1.5.0+版本):当系统CPU使用率超过阈值即触发系统保护(取值范围0.0-1.0),比较灵敏。
  • 平均RT:当单台机器上所有入口流量的平均RT达到阈值即触发系统保护,单位是毫秒。
  • 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
  • 入口QPS:当单台机器上所有入口流量的QPS达到阈值即触发系统保护。

案例:测试接口中的所有方法qps都是1。