微服务熔断原理

一、问题的产生(为什么要引入熔断)

雪崩效应

    微服务架构的应用系统通常包含多个服务层。微服务之间通过网络进行通信,从而支撑起整个应用系统,因此,微服务之间难免存在依赖关系。我们知道,任何微服务都并非100%可用,网络往往也很脆弱,因此难免有些请求会失败。

    我们常把“基础服务故障”导致“级联故障”的现象称为雪崩效应。雪崩效应描述的是提供者不可用导致消费者不可用,并将不可用逐渐放大的过程。

    如下图所示:A作为服务提供者,B为A的服务消费者,C和D是B的服务消费者。A不可用引起了B的不可用,并将不可用像滚雪球一样放大到C和D时,雪崩效应就形成了。

 

二、如何容错

    要想防止雪崩效应,必须有一个强大的容错机制。该容错机制需要实现以下两点。

1.为网络请求设置超时

        一次远程调用对应着一个线程/进程。如果响应太慢,这个线程/进程就得不到释放。而线程/进程又对应着系统资源,如果得不到释放的线程/进程越积越多,资源就会被逐渐耗尽,最终导致服务的不可用。

因此,必须为每个网络请求设置超时,让资源尽快释放

2.使用熔断器模式

三、熔断器模式(工作原理)

    熔断器的原理很简单,如同电力过载保护器。它可以实现快速失败,如果它在一段时间内侦测到许多类似的错误,会强迫其以后的多个调用快速失败,不再访问远程服务器,从而防止应用程序不断地尝试执行可能会失败的操作,使得应用程序继续执行而不用等待修正错误,或者浪费CPU时间去等到长时间的超时产生。熔断器也可以使应用程序能够诊断错误是否已经修正,如果已经修正,应用程序会再次尝试调用操作。

    熔断器模式就像是那些容易导致错误的操作的一种代理。这种代理能够记录最近调用发生错误的次数,然后决定使用允许操作继续,或者立即返回错误。 
    熔断器开关相互转换的逻辑如下图:

—正常情况下,断路器关闭,可正常请求服务。

—当一段请求过后,请求失败率达到一定阈值,例如错误率50%,熔断器就会打开,因此,不会再去请求依赖的服务。

—断路器打开一段时间后,会自动进入“半开”状态。此时,熔断器可允许少量请求访问依赖的服务。如果成功,则关闭熔断器;否则继续转为打开状态。

 

Resilience4j在请求数量达到设置的缓冲池大小时才会进行失败率计算,计算完成后会清空缓冲池,所以熔断的间隔是一轮缓冲池大小,不是每请求失败一次就熔断一次,不是用滑动窗口计算失败率,也跟时间无关,缓冲池逻辑结构图如下所示:

 Ring Bit Buffer

熔断器的环形缓冲池

 

熔断器就是保护服务高可用的最后一道防线。

 

 

        

                                          Resilience4j CircuitBreaker工作流程图               

 

 

 熔断器方案:Resilience4j CircuitBreaker,Resilience4j retrofit。http://resilience4j.github.io/resilience4j/

Resilience4j CircuitBreaker熔断器核心实现源码:

熔断器通过circuitBreaker.onSuccess(durationInNanos)和 circuitBreaker.onError(durationInNanos, throwable)来统计失败率

static <T> Supplier<T> decorateSupplier(CircuitBreaker circuitBreaker, Supplier<T> supplier){

    return () -> {

        CircuitBreakerUtils.isCallPermitted(circuitBreaker);    //判断熔断器,若打开则抛出IOException

        long start = System.nanoTime();

        try {

            T returnValue = supplier.get();                     //执行请求

            long durationInNanos = System.nanoTime() - start;

            circuitBreaker.onSuccess(durationInNanos);          //统计请求成功结果

            return returnValue;

        catch (Throwable throwable) {

            long durationInNanos = System.nanoTime() - start;

            circuitBreaker.onError(durationInNanos, throwable); //统计请求失败结果

            throw throwable;

        }

    };

}

 

onSuccess()和onFailure()代码

float onSuccess() {

      int currentNumberOfFailedCalls = ringBitSet.setNextBit(false);

      return getFailureRate(currentNumberOfFailedCalls);

  }

 

 

 float onError() {

      int currentNumberOfFailedCalls = ringBitSet.setNextBit(true);

      return getFailureRate(currentNumberOfFailedCalls);

  }

 

 

private float getFailureRate(int numberOfFailedCalls) {

      if (getNumberOfBufferedCalls() < ringBufferSize) {    //可以看出熔断是在请求数达到ringBufferSize(默认值10或5)时才决定是否熔断

          return -1.0f;

      }

      return numberOfFailedCalls * 100.0f / ringBufferSize;   

  }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值