resilience4j:熔断器核心配置详解

    Resilience4j提供了熔断、高频控制、隔离、限流、限时、重试等多种高可用机制。这里我们看一下熔断机制,通过熔断器配置来理解熔断机制。

一、概述

1、定制化熔断器配置

    官网提供的定制化熔断器配置的模板:

// Create a custom configuration for a CircuitBreaker
CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
    .failureRateThreshold(50)
    .waitDurationInOpenState(Duration.ofMillis(1000))
    .ringBufferSizeInHalfOpenState(2)
    .ringBufferSizeInClosedState(2)
    .recordExceptions(IOException.class, TimeoutException.class)
    .ignoreExceptions(BusinessException.class, OtherBusinessException.class)
    .enableAutomaticTransitionFromOpenToHalfOpen()
    .build();

    CircuitBreakerConfig还提供了一系列的get方法来访问CircuitBreakerConfig实例的一系列配置:

2、熔断器的状态转换

    熔断器的常用状态有三种:打开状态、半打开状态和关闭状态。

  • 关闭状态:这种是初始状态,即没有触发熔断的情况下,熔断器就保持关闭状态,说明此时服务稳定,不需要开启熔断;
  • 打开状态:当达到了熔断的阈值,熔断器就会进入打开状态,此时熔断器会阻断一些调用下游服务的请求;
  • 半打开状态:当熔断器持续保持打开状态一段时间后,会进入半打开状态,放行一定比例的请求下游服务的调用,根据这些请求的成功率判断,熔断器是恢复关闭状态还是再次进入打开状态。

3、熔断器配置的内容

    官网中对熔断器配置的介绍:resilience4j官网

the failure rate threshold in percentage above which the CircuitBreaker should trip open and start short-circuiting calls

the wait duration which specifies how long the CircuitBreaker should stay open, before it switches to half open

the size of the ring buffer when the CircuitBreaker is half open

the size of the ring buffer when the CircuitBreaker is closed

a custom CircuitBreakerEventListener which handles CircuitBreaker events

a custom Predicate which evaluates if an exception should be recorded as a failure and thus increase the failure rate

a list of exceptions which should increase failure count

a list of exceptions which should be ignored and not increase failure count

    熔断器的配置,主要包括如下内容:

  • 触发熔断的失败率阈值:failureRateThreshold
  • 熔断器从打开状态到半开状态的等待时间:waitDurationInOpenState
  • 熔断器在半开状态时环状缓冲区的大小:ringBufferSizeInHalfOpenState
  • 熔断器在关闭状态时环状缓冲区的大小:ringBufferSizeInClosedState
  • 处理熔断器事件的定制监听器:可以在获取到熔断器实例后再去注册
  • 评估异常是否被记录为失败事件的定制化谓词函数Predicate:recordFailure
  • 会触发失败的异常类型:recordExceptions
  • 不会触发失败的异常类型:ignoreExceptions

    下面来一项一项介绍上述配置。

二、配置详解

1、触发熔断的失败率阈值

1、作用描述:

    熔断器在关闭状态会取最新的n个请求(这里的n指的是“熔断器在关闭状态时环状缓冲区的大小”),如果这n个请求中,失败的比例大于或等于“触发熔断的失败率阈值”,那么就会触发熔断,熔断器进入“打开”状态。

2、设置函数:failureRateThreshold

3、默认值:DEFAULT_MAX_FAILURE_THRESHOLD = 50;

4、源码:

        public Builder failureRateThreshold(float failureRateThreshold) {
            if (failureRateThreshold <= 0 || failureRateThreshold > 100) {
                throw new IllegalArgumentException("failureRateThreshold must be between 1 and 100");
            }
            this.failureRateThreshold = failureRateThreshold;
            return this;
        }

5、注意事项:

    函数的入参是float类型,表示失败率的值,入参的数值应该大于0且小于等于100。

2、熔断器从打开状态到半开状态的等待时间

1、作用描述:

    熔断器的失败率达到“触发熔断的失败率阈值”后首先会进入“打开”状态,然后维持一段时间的“打开”状态后会进入“半打开”状态。这段时间,就是通过“熔断器从打开状态到半开状态的等待时间”来指定的。

2、设置函数:waitDurationInOpenState

3、默认值:DEFAULT_WAIT_DURATION_IN_OPEN_STATE = 60; // Seconds

4、源码:

        public Builder waitDurationInOpenState(Duration waitDurationInOpenState) {
            if (waitDurationInOpenState.getSeconds() < 1) {
                throw new IllegalArgumentException("waitDurationInOpenState must be at least 1000[ms]");
            }
            this.waitDurationInOpenState = waitDurationInOpenState;
            return this;
        }

5、注意事项:

    函数的入参是Duration类型,表示一段时间,例如:Duration.ofMillis(1000),表示1000ms;

    函数的入参表示的时间段,要求大于或等于1s。

3、熔断器在半开状态时环状缓冲区的大小

1、作用描述:

        熔断器在半开状态会取最新的n个请求(这里的n指的是“熔断器在半开状态时环状缓冲区的大小”),根据这n个请求判断是否会恢复关闭状态。

2、设置函数:ringBufferSizeInHalfOpenState

3、默认值:DEFAULT_RING_BUFFER_SIZE_IN_HALF_OPEN_STATE = 10;

4、源码:

        public Builder ringBufferSizeInHalfOpenState(int ringBufferSizeInHalfOpenState) {
            if (ringBufferSizeInHalfOpenState < 1 ) {
                throw new IllegalArgumentException("ringBufferSizeInHalfOpenState must be greater than 0");
            }
            this.ringBufferSizeInHalfOpenState = ringBufferSizeInHalfOpenState;
            return this;
        }

5、注意事项:

    函数的入参要求大于等于1;

    这里需要注意:如果请求次数低于环状缓冲区的大小,那么即使失败率已经低于了阈值,依然不会触发熔断关闭!!!

4、熔断器在关闭状态时环状缓冲区的大小

1、作用描述:

        熔断器在关闭状态会取最新的n个请求(这里的n指的是“熔断器在关闭状态时环状缓冲区的大小”),根据这n个请求判断是否会进入打开状态。

2、设置函数:ringBufferSizeInClosedState

3、默认值:DEFAULT_RING_BUFFER_SIZE_IN_CLOSED_STATE = 100;

4、源码:

        public Builder ringBufferSizeInClosedState(int ringBufferSizeInClosedState) {
            if (ringBufferSizeInClosedState < 1) {
                throw new IllegalArgumentException("ringBufferSizeInClosedState must be greater than 0");
            }
            this.ringBufferSizeInClosedState = ringBufferSizeInClosedState;
            return this;
        }

5、注意事项:

    函数的入参要求大于等于1;

    这里需要注意:如果请求次数低于环状缓冲区的大小,那么即使失败率已经超过了失败率阈值,依然不会触发熔断!!!

5、处理熔断器事件的定制监听器

1、作用描述:

        熔断器事件的定制监听器,用来监听熔断器的事件(CircuitBreakerEvent)。

2、使用示例:

// 针对每种不同的事件进行设置
circuitBreaker.getEventPublisher()
    .onSuccess(event -> logger.info(...))
    .onError(event -> logger.info(...))
    .onIgnoredError(event -> logger.info(...))
    .onReset(event -> logger.info(...))
    .onStateTransition(event -> logger.info(...));

// 对所有的事件生效
circuitBreaker.getEventPublisher()
    .onEvent(event -> logger.info(...));

3、事件的存储:

    可以使用CircularEventConsumer将事件存储在缓存中:

CircularEventConsumer<CircuitBreakerEvent> ringBuffer = new CircularEventConsumer<>(10);
circuitBreaker.getEventPublisher().onEvent(ringBuffer);
List<CircuitBreakerEvent> bufferedEvents = ringBuffer.getBufferedEvents()

    还可以将EventPublisher转换为RxJava/Reactor的事件流,该方法的优势在于,可以进一步指定调度器进行异步化处理:

RxJava2Adapter.toFlowable(circuitBreaker.getEventPublisher())
    .filter(event -> event.getEventType() == Type.ERROR)
    .cast(CircuitBreakerOnErrorEvent.class)
    .subscribe(event -> logger.info(...))

6、评估异常是否被记录为失败事件的定制化谓词函数Predicate

1、作用描述:

    这里特定把官网给的词语“Predicate”带上了,因为“谓词函数”这个概念不好理解,但是学过Java的人对“Predicate”就比较熟悉了。这里的Predicate和Java的Predicate接口作用基本类似,也是用来判断一个条件是否成立:评估异常是否应该被记录为失败事件。

2、设置函数:recordFailure

3、默认值:

    默认会认为所有的异常都会触发熔断的失败:

public static final Predicate<Throwable> DEFAULT_RECORD_FAILURE_PREDICATE = (throwable) -> true;

4、源码:

        /**
         * Configures a Predicate which evaluates if an exception should be recorded as a failure and thus increase the failure rate.
         * The Predicate must return true if the exception should count as a failure, otherwise it must return false.
         *
         * @param predicate the Predicate which evaluates if an exception should be recorded as a failure and thus trigger the CircuitBreaker
         * @return the CircuitBreakerConfig.Builder
         */
        public Builder recordFailure(Predicate<Throwable> predicate) {
            this.recordFailurePredicate = predicate;
            return this;
        }

5、注意事项:

    如果不进行设置,默认会认为所有的异常类型都会触发熔断的失败,因为默认会直接返回true。

7、会触发失败的异常类型

1、作用描述:

        指的是熔断器接收到哪些异常的时候才会触发熔断。

2、设置函数:recordExceptions

3、默认值:

    默认为空数组:private Class<? extends Throwable>[] recordExceptions = new Class[0];    

4、源码:

        /**
         * Configures a list of error classes that are recorded as a failure and thus increase the failure rate.
         * Any exception matching or inheriting from one of the list should count as a failure, unless ignored via
         * @see #ignoreExceptions(Class[]) ). Ignoring an exception has priority over recording an exception.
         *
         * Example:
         *  recordExceptions(Throwable.class) and ignoreExceptions(RuntimeException.class)
         *  would capture all Errors and checked Exceptions, and ignore unchecked
         *
         *  For a more sophisticated exception management use the
         *  @see #recordFailure(Predicate) method
         *
         * @param errorClasses the error classes that are recorded
         * @return the CircuitBreakerConfig.Builder
         */
        @SafeVarargs
        public final Builder recordExceptions(Class<? extends Throwable>... errorClasses) {
            this.recordExceptions = errorClasses != null ? errorClasses : new Class[0];
            return this;
        }

5、注意事项:

    ignoreExceptions的优先级高于recordExceptions,如果在ignoreExceptions中配置了异常,那么即使在recordExceptions中进行了配置,依然不会作为触发失败的异常。

8、不会触发失败的异常类型

1、作用描述:

        指的是熔断器接收到哪些异常的时候不会触发熔断。

2、设置函数:ignoreExceptions

3、默认值:

    默认为空数组:private Class<? extends Throwable>[] ignoreExceptions = new Class[0];

4、源码:

        /**
         * Configures a list of error classes that are ignored as a failure and thus do not increase the failure rate.
         * Any exception matching or inheriting from one of the list will not count as a failure, even if marked via
         * @see #recordExceptions(Class[]) . Ignoring an exception has priority over recording an exception.
         *
         * Example:
         *  ignoreExceptions(Throwable.class) and recordExceptions(Exception.class)
         *  would capture nothing
         *
         * Example:
         *  ignoreExceptions(Exception.class) and recordExceptions(Throwable.class)
         *  would capture Errors
         *
         *  For a more sophisticated exception management use the
         *  @see #recordFailure(Predicate) method
         *
         * @param errorClasses the error classes that are recorded
         * @return the CircuitBreakerConfig.Builder
         */
        @SafeVarargs
        public final Builder ignoreExceptions(Class<? extends Throwable>... errorClasses) {
            this.ignoreExceptions = errorClasses != null ? errorClasses : new Class[0];
            return this;
        }

5、注意事项:

    ignoreExceptions的优先级高于recordExceptions

三、重要细节汇总

1、failureRateThreshold(float failureRateThreshold)函数配置的“触发熔断的失败率阈值”,不仅是判断是否需要从熔断关闭状态进入熔断打开状态(失败率大于或等于阈值)的门限,同样是用在熔断半开状态,判断接下来熔断器状态是进入关闭状态(失败率小于阈值),还是进入打开状态(失败率大于或等于阈值);

2、环状缓冲区有两个,分别用于关闭状态和半开状态。两个环状缓冲区都要求,请求次数必须大于或等于缓冲区大小的情况下,才会触发失败率相关的判断。例如熔断器处于关闭状态,关闭状态的缓冲区大小是10,失败率是50(即50%),如果请求次数只有9次,即使9次请求全部是失败的,熔断器也不会立即进入熔断打开状态,而是会等待第10次请求发生后才会进行状态的改变;

3、熔断器在接受到异常的情况下,才有可能会增加失败次数。在默认情况下,熔断器在接受到任意异常的时候,都会增加失败次数;

4、当用户使用熔断器的时候,不一定要定制熔断器配置,也可以直接使用默认的熔断器配置创建熔断器。这个创建过程,也是通过熔断器注册中心CircuitBreakerRegistry的实例来实现的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值