--- title: Resilience4j熔断器Circuit Breaker date: 2020-06-13 tags: Java --- # 介绍 从这一篇起我们将来讲述 Resilience4j熔断器的使用spring中如何使用以及背后的原理(当然要结合源码来探讨)。 # Resilience4j配置 任何组件都会有配置 可以说配置是一个组件的基础 无法绕过它。例如我们前面说的Archaius作为NetflixOss的配置基础 Hystrix 、Ribbon都是在其基础上进行扩展的 ,可以说它在整个NetflixOss中扮演者重要的角色。 而今天我们的主角的配置功能不像Archaius那么复杂 需要专门拿专栏来讲述。 ## 创建配置实例 ```java CircuitBreakerConfig.ofDefaults(); CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom() .slidingWindowSize(10) .slidingWindowType(CircuitBreakerConfig.SlidingWindowType.COUNT_BASED) .build(); ``` ## 各个配置项含义 ```java CircuitBreakerConfig.custom() .slidingWindowType(CircuitBreakerConfig.SlidingWindowType.COUNT_BASED) .slidingWindowSize(10) .automaticTransitionFromOpenToHalfOpenEnabled(true) .currentTimestampFunction( clock -> clock.millis() , TimeUnit.MILLISECONDS) .failureRateThreshold(0.1f) .ignoreException(throwable -> { if (throwable instanceof NullPointerException){ return false; } return true; }) .maxWaitDurationInHalfOpenState(Duration.ofSeconds(60)) .minimumNumberOfCalls(1) .slowCallDurationThreshold(Duration.ofSeconds(60)) .slowCallRateThreshold(0.1f) .waitDurationInOpenState(Duration.ofMinutes(1)).build(); ``` * _**slidingWindowType:**_ 滑动窗口类型。还记得上一篇我们介绍过 **Resilience4J可以在基于计数的滑动窗口和基于时间的滑动窗口之间进行选择。** * _**waitDurationInOpenState:**_ 将间隔功能配置为具有固定的等待时间,该间隔时间控制CircuitBreaker保持打开状态多长时间,然后再切换到半打开状态。 **默认值为60秒**。 * _**automaticTransitionFromOpenToHalfOpenEnabled :**_ 一旦waitDurationInOpenState通过,启用从OPEN到HALF_OPEN状态的自动转换 * _**currentTimestampFunction :**_ 该函数返回CircuitBreaker的当前时间戳。默认实现使用System.nanoTime()来计算当前时间戳。当然我们可以通过设置该函数来实现毫秒值 * _**slidingWindowSize:**_ 滑动窗口的大小 如果窗口类型是基于计数的滑动窗口 那么该值得含义就是固定数组的大小存放每次请求的结果。如果窗口类型是 基于时间的滑动窗口 那么该值得含义就是窗口大小 例如10 就会有10个存储桶每个存储桶窗口大小是1s * _**failureRateThreshold :**_ 以百分比配置故障率阈值。如果故障率等于或大于阈值,则CircuitBreaker转换为打开状态并开始短路呼叫。 阈值必须大于0且不大于100。默认值为50。 * _**ignoreException :**_ 配置是否需要忽略的异常,如果有需要忽略的异常不计入失败 可以通过这个配置项来配置 * _**minimumNumberOfCalls :**_ 在CircuitBreaker可以计算错误率之前,配置所需的最小呼叫数(每个滑动窗口时段)。例如,如果值为10,那么在可以计算失败率之前,必须至少记录10个呼叫。如果仅记录了9个呼叫,则即使所有9个呼叫均失败,CircuitBreaker也不会转换为打开。默认为100。 * _**maxWaitDurationInHalfOpenState :**_ 使用固定的等待时间配置CircuitBreaker,该持续时间控制CircuitBreaker在切换为打开之前应保持半开状态的时间。这是一个可选参数。默认情况下,CircuitBreaker将保持半开状态,直到 minimumNumberOfCalls成功或失败为止。 * _**slowCallDurationThreshold:**_ 慢执行的时间阈值,如果大于该值的执行被认为是慢执行 会被统计。如果当慢执行的比例超过一定比例的时候就会被熔断。 **默认值60s** * _**slowCallRateThreshold :**_ 上面说过 **如果当慢执行的比例超过一定比例的时候就会被熔断** 那这个值就是配置慢执行的比例的。 **默认为100**。 也就意味着所有的请求都比slowCallDurationThreshold慢 才会被熔断。 * _**waitIntervalFunctionInOpenState:**_ 配置间隔功能,该功能控制CircuitBreaker在打开到半开状态之前应保持打开状态多长时间。默认的时间间隔函数返回固定的60秒等待时间。如果需要指数退避算法,则自定义间隔函数很有用。 * _**recordException:**_ 是否应将异常记录为失败,从而提高失败率。如果异常应该算作失败,则谓词必须返回true。如果异常应将视为成功,则谓词必须返回false,除非ignoreExceptions明确忽略了该异常。 * _**writableStackTraceEnabled :**_ 启用可写的堆栈跟踪。设置为false时, **Exception#getStackTrace**返回长度为零的数组。当断路器打开时,这可以用来减少垃圾日志,因为已知异常的原因。 # 配置如何用 上面说了那么多的配置 那么这些配置到底是怎么使用的。我们通过一个demo先展示一下。 ```java given(helloWorldService.returnHelloWorld()).willReturn("hello word"); CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom() .slidingWindowSize(10) .slidingWindowType(CircuitBreakerConfig.SlidingWindowType.COUNT_BASED) .build(); CircuitBreaker circuitBreaker = CircuitBreaker.of("test", circuitBreakerConfig); Supplier stringSupplier = circuitBreaker.decorateSupplier(helloWorldService::returnHelloWorld); assertThat(stringSupplier.get()).isEqualTo("hello word"); ``` # 结语 断路器的配置到这就结束了。上面一坨的配置后面用到的时候再回头来查就可以了,无需死记。Resilience4j属于轻量级的框架 本身并没有依赖专门的配置工具,自己实现的配置也是相当的简单。值得注意的是Resilience4j每一个模块都会有自己的配置 这些配置是相互独立的。例如:重试功能的配置 _**RateLimiterConfig**_ 、限流模块的配置 _**RateLimiterConfig**_ 等等。这些我们后面遇到的时候就不再花时间介绍了。相对于熔断的配置 其他模块的配置还算简单。