一、简介
Resilience4j 是一个轻量级的容错组件,其灵感来自于 Hystrix,但主要为 Java 8 和函数式编程所设计。
它更适用于通过注解形式的熔断限流处理。
轻量级体现在其只用 Vavr 库,没有任何外部依赖。而 Hystrix 依赖了 Archaius,Archaius 本身又依赖很多第三方包,例如 Guava、Apache Commons Configuration 等等。
要使用 Resilience4j,不需要引入所有依赖,只需要引入你所需的模块。一般情况下,只需要引入 resilience4j-spring-boot2
就够了。
二、熔断器差异
Resilience4j 的熔断状态与 Hystrix 相同,但他们记录请求状态的数据结构有所不同:
Hystrix 是使用滑动窗口来进行存储的,而 Resilience4j 采用的是 Ring Bit Buffer
(环形缓冲区)。Ring Bit Buffer 在内部使用 BitSet
这样的数据结构来进行存储,结构如下图所示:
每一次请求的成功或失败状态只占用一个 bit 位,与 boolean 数组相比更节省内存。BitSet 使用 long[] 数组来存储这些数据,意味着 16
个值(64 bit)的数组可以存储 1024
个调用状态。
计算失败率需要填满环形缓冲区。这点跟Sentinel的最小阈值一样。
三、注解比较
@Retry
> @CircuitBreaker
> @RateLimiter
> @TimeLimiter
> @Bulkhead
@Retry
在执行失败时,进行重试的行为。多次重试失败到达上限时,Resilience4j 会抛出MaxRetriesExceeded
异常,然后就进入 fallback 降级处理。@CircuitBreaker
通过不同的 Throwable 异常,我们可以进行不同的 fallback 降级处理。极端情况下,Resilience4j 熔断器打开时,不会执行该方法,而是直接抛出CallNotPermittedException
异常,然后也是进入 fallback 降级处理。@RateLimiter
默认情况下,采用 AtomicRateLimiter 基于令牌桶限流算法实现限流。在请求被限流时,Resilience4j 不会执行该方法,而是直接抛出RequestNotPermitted
异常,然后就进入 fallback 降级处理。
注意,@RateLimiter 注解的 fallbackMethod 属性对应的 fallback 方法,不仅仅处理被限流时抛出的 RequestNotPermitted 异常,也处理该方法执行时的普通异常。@TimeLimiter
限制任务的执行时长,在超过时抛出TimeoutException
异常,然后就进入 fallback 降级处理。需要搭配线程池类型的 Bulkhead。@Bulkhead
在请求被流控时,并不是直接失败抛出BulkheadFullException
异常,而是阻塞等待最大max-wait-duration
微秒,看看是否能够请求通过。它也处理该方法执行时的普通异常。
四、相关配置
resilience4j: # Resilience4j 的重试 Retry 配置项,对应 RetryProperties 属性类 retry: instances: backendE: max-retry-Attempts: 3 # 最大重试次数。默认为 3 wait-duration: 5s # 下次重试的间隔,单位:微秒。默认为 500 毫秒 retry-exceptions: # 需要重试的异常列表。默认为空 ingore-exceptions: # 需要忽略的异常列表。默认为空 # Resilience4j 的熔断器配置项,对应 CircuitBreakerProperties 属性类 circuitbreaker: instances: backendA: failure-rate-threshold: 50 # 熔断器关闭状态和半开状态使用的同一个失败率阈值,单位:百分比。默认为 50 ring-buffer-size-in-closed-state: 5 # 熔断器关闭状态的缓冲区大小,不会限制线程的并发量,在熔断器发生状态转换前所有请求都会调用后端服务。默认为 100 ring-buffer-size-in-half-open-state: 5 # 熔断器半开状态的缓冲区大小,会限制线程的并发量。例如,缓冲区为 10 则每次只会允许 10 个请求调用后端服务。默认为 10 wait-duration-in-open-state : 5000 # 熔断器从打开状态转变为半开状态等待的时间,单位:微秒 automatic-transition-from-open-to-half-open-enabled: true # 如果置为 true,当等待时间结束会自动由打开变为半开;若置为 false,则需要一个请求进入来触发熔断器状态转换。默认为 true register-health-indicator: true # 是否注册到健康监测 # Resilience4j 的限流器配置项,对应 RateLimiterProperties 属性类 ratelimiter: instances: backendB: limit-for-period: 1 # 每个周期内,允许的请求数。默认为 50 limit-refresh-period: 10s # 每个周期的时长,单位:微秒。默认为 500 timeout-duration: 5s # 被限流时,阻塞等待的时长,单位:微秒。默认为 5s register-health-indicator: true # 是否注册到健康监测 # Resilience4j 的信号量 Bulkhead 配置项,对应 BulkheadConfigurationProperties 属性类 bulkhead: instances: backendC: max-concurrent-calls: 1 # 并发调用数。默认为 25 max-wait-duration: 5s # 并发调用到达上限时,阻塞等待的时长,单位:微秒。默认为 0 # Resilience4j 的超时限制器 TimeLimiter 配置项,对应 TimeLimiterProperties 属性类 timelimiter: instances: backendF: timeout-duration: 1s # 等待超时时间,单位:微秒。默认为 1 秒 cancel-running-future: true # 当等待超时时,是否关闭取消线程。默认为 true # Resilience4j 的线程池 Bulkhead 配置项,对应 ThreadPoolBulkheadProperties 属性类 thread-pool-bulkhead: instances: backendD: max-thread-pool-size: 1 # 线程池的最大大小。默认为 Runtime.getRuntime().availableProcessors() core-thread-pool-size: 1 # 线程池的核心大小。默认为 Runtime.getRuntime().availableProcessors() - 1 queue-capacity: 100 # 线程池的队列大小。默认为 100 keep-alive-duration: 100s # 超过核心大小的线程,空闲存活时间。默认为 20 毫秒
五、监控端点
Resilience4j 还扩展了许多与第三方监控系统对接的功能,如:
Metrics endpoint
:纯 Endpoint 结尾。
/actuator/metrics
路径下可以看到 Resilience4j 提供的所有 Metrics 监控指标。Health endpoint
:HealthIndicator 结尾。
/actuator/health
路径下可以看到 CircuitBreaker 和 RateLimiter 的健康状态。Events endpoint
:EventsEndpoint 结尾。
/actuator/类型events
路径下可以看到 Resilience4j当前类型的 Event 事件。