熔断器的原理以及使用和源码解析

01、什么是熔断

在分布式系统中,各服务间的相互调用更加频繁,上下游调用中充满了可能性,一个服务可能会被很多其他服务依赖并调用,在这个过程中如果某个服务由于某种原因出错(业务出错、负载过高),可能会导致整个分布式调用链路失败:

上面这个过程最终可能会导致全链路瘫痪(服务雪崩),此时需要一种可以解决上述问题的策略,此策略设计目标为:

  1. 在发现有服务调用失败后,及时计算失败率

  2. 失败率达到某种阈值时,切断与该服务的所有交互,服务走切断后的自定义逻辑

  3. 切断并且不再调用该服务后主动监听被切断的服务是否已经恢复了处理能力,若恢复,则继续让其提供服务

这个策略被放进图1中,就变成了下面这样:

这个过程中,C服务在自己出问题的情况下,并不会像图1里那样仍然有大量流量打进来,也不会影响到上游服务,这个结果让调用链看起来比图1更加的稳定,这个过程就叫熔断。

针对这个过程,可以看到在C不可用时,B走了熔断后的降级逻辑,这个逻辑可以自定义,如果C在整个调用链里属于那种必须要成功的服务,那么这里的逻辑就可以是直接抛错,如果C属于那种失败了也无所谓,不影响整个业务处理,那么降级逻辑里就可以不做处理,例如下面的场景:

类似这种接口,降级策略很适合不做处理,返回空信息即可,这样最坏的情况就是页面少了某个板块的信息,可能会对用户造成不太好的体验,但是不影响其对外服务,被熔断的服务恢复后页面也会重新回归正常。熔断后的降级处理方式是件值得思考的事情,熔断和降级是相互独立的概念,熔断后必然会有降级操作(哪怕直接抛异常也是一种降级策略),这个降级操作是熔断这个动作导致的,所以很多时候会把熔断和降级放在一起说,其实降级还可以由其他动作触发,比如限流后抛出“系统繁忙”,这也是一种降级策略,只不过它是由限流触发的,再比如通过开关埋点在系统负载过高时主动关停一些次要服务来提升核心功能的响应速度,这也是一种降级策略,降级是最终产物,而产生它的方式有很多种。

02、Resilience4j中的熔断器

03、:Resilience4j是什么?

它是一个轻量、易用、可组装的高可用框架,支持熔断、高频控制、隔离、限流、限时、重试等多种高可用机制。本篇文章只关注其熔断部分。

04、:如何使用?

通过第一部分的介绍,可以认为一个熔断器必须要具备统计单位请求内的错误率、全熔断、半熔断放量、恢复这几个流程,带着这个流程,下面来介绍下Resilience4j里熔断器的用法。

通过图2里服务B调用服务C的例子,现在利用java类来进行简单模拟下这个流程。

首先定义ServerC类,用于模拟服务C:

public class ServerC {
    //使用该方法模拟服务C获取C信息的方法,假设现在服务C的getCInfo方法里有个bug,当输入的id为0时报错,其他情况正常
    public String getCInfo(int id) {
        if (id == 0) {
            throw new RuntimeException("输入0异常");
        }
        return "id=" + id + "的C信息";
    }
}

再定义ServerB类,用于模拟服务B,这里给服务B调用服务C方法那里加上熔断器处理,注意这个类里的注释,会详细说明熔断器的主要配置项以及其使用方法:

public class ServerB {

    private CircuitBreakerRegistry breakerRegistry;

    private ServerC serverC = new ServerC(); //让服务B持有一个服务C的引用,用来表示正常服务间调用里的一个连接引用

    ServerB() {
        //初始化breaker注册器,可以利用该对象生产各种breaker对象(注:凡是用同一个注册器生产出来的breaker,都会继承注册器的配置属性)
        breakerRegistry = CircuitBreakerRegistry.of(CircuitBreakerConfig.custom() //of方法里面放的就是breaker的配置属性对象
                .enableAutomaticTransitionFromOpenToHalfOpen() //开启从全开状态经过下面的waitDurationInOpenState时间后自动切换到半开状态
                .failureRateThreshold(50) //熔断器闭合状态下的错误率阈值,50表示50%,如果错误率达到这个阈值,那么熔断器将进入全熔断状态
                .ringBufferSizeInClosedState(100) //熔断器闭合状态下,以该值为单位请求数,计算错误率,跟上面错误率阈值综合理解,这个值表示至少有100个请求,且错误50个以上才会触发全熔断
                .ringBufferSizeInHalfOpenState(10) //熔断器半熔断状态下,以该值为单位请求数,计算错误率,跟上面错误率阈值综合理解,这个值表示至少有10个请求,且错误5个以上会再次触发全熔断,相比闭合状态,半熔断状态下更容易再次进入全熔断状态
                .waitDurationInOpenState(Duration.ofMillis(1000L)) //熔断器全熔断状态持续的时间,全熔断后经过该时间后进入半熔断状态
                .build());
    }

    //服务B通过服务C来获取到C的info信息,该方法就是用来干这个的,它会发起对服务C的调用
    public String getCInfo(int id) {
        //breaker对象是按照name划分全局单例的
        CircuitBreaker breaker = breakerRegistry.circuitBreaker("getCInfo"); //这里给熔断器取个名,一般情况就是一个服务的path或方法名
        try {
            return breaker.executeCallable(() -> serverC.getCInfo(id));
        } catch (CircuitBreakerOpenException e) { //一旦抛出该异常说明已经进入全熔断状态
            //被熔断后的降级逻辑
            return "服务C出错,触发服务B的降级逻辑";
        } catch (Exception e) {
     
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值