Resilience4J 介绍

Netflix Hystrix 断路器是 Spring Cloud 中最早就开始支持的一种服务调用容错解决方案,但是目前的 Hystrix 已经处于维护模式了,虽然这并不影响已经上线的项目,并且在短期内,你甚至也可以继续在项目中使用 Hystrix 。但是长远来看,处于维护状态的 Hystrix 走下历史舞台只是一个时间问题,特别是在 Spring Cloud Greenwich 版中,官方已经给出了 Hystrix 的建议替代方案。如下图:

Resilience4j 是 Spring Cloud Greenwich 版推荐的容错解决方案,它是一个轻量级的容错库,受 Netflix Hystrix 的启发而设计,它专为 Java 8 和函数式编程而设计。

Resilience4j 非常轻量级,因为它的库只使用 Vavr (以前称为 Javaslang ),它没有任何其他外部库依赖项。相比之下, Netflix Hystrix 对Archaius 具有编译依赖性,这导致了更多的外部库依赖,例如 Guava 和 Apache Commons 。而如果使用Resilience4j,你无需引用全部依赖,可以根据自己需要的功能引用相关的模块即可。

Resilience4j 也提供了一系列增强微服务可用性的功能,主要功能如下:

  • 断路器
  • 限流
  • 基于信号量的隔离
  • 缓存
  • 限时
  • 请求重试

接下来,我们就先来看通过一个普通的Maven项目来看 Resilience4j 中这几个功能的基本用法。

上面提到的 Resilience4j 中的功能,每一个功能都对应了一个依赖。我们创建好Maven项目后,再添加单元测试依赖:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

一、Resilience4j 的功能介绍

断路器有三种正常状态:完全打开OPEN,半开HALF_OPEN,关闭CLOSED,还有两种通过设置的强制状态:强制不可用DISABLED,强制打开FORCED_OPEN。

断路器初始化

使用 Resilience4j 提供的断路器功能,需要我们首先加入如下依赖:

<dependency>
    <groupId>io.github.resilience4j</groupId>
    <artifactId>resilience4j-circuitbreaker</artifactId>
    <version>1.5.0</version>
</dependency>

这个库提供了一个基于 ConcurrentHashMap 的 CircuitBreakerRegistry ,CircuitBreakerRegistry 是线程安全的,并且是原子操作。开发者可以使用 CircuitBreakerRegistry 来创建和检索 CircuitBreaker 的实例 ,开发者可以直接使用默认的全局CircuitBreakerConfig 为所有 CircuitBreaker 实例创建 CircuitBreakerRegistry ,如下所示:

CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults();

当然开发者也可以提供自己的 CircuitBreakerConfig ,然后根据自定义的 CircuitBreakerConfig 来创建一个 CircuitBreakerRegistry 实例,进而创建 CircuitBreaker 实例。如果我们使用自定义的 CircuitBreakerConfig :

CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
        .failureRateThreshold(50) //默认为50,即失败率阈值为50%, 超过这个阈值,断路器就会打开
        .waitDurationInOpenState(Duration.ofMillis(1000)) // 用来指定断路器从OPEN到HALF_OPEN状态等待的时长,默认是60秒
        .permittedNumberOfCallsInHalfOpenState(2) //熔断器半开时的限制线程的并发量
        .slidingWindowType(CircuitBreakerConfig.SlidingWindowType.COUNT_BASED) // 滑动窗口类型,有基于时间TIME_BASED和基于计数COUNT_BASED
        .slidingWindowSize(2) //滑动窗口大小,默认是基于计数的滑动窗口类型
        .automaticTransitionFromOpenToHalfOpenEnabled(false) //当waitDurationInOpenState时间一过,是否自动从OPEN切换到HALF_OPEN,默认为false
        .build();
// 配置CircuitBreakerRegistry
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.of(circuitBreakerConfig);
// 创建两个断路器
CircuitBreaker circuitBreaker2 = circuitBreakerRegistry.circuitBreaker("otherName");
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("uniqueName", circuitBreakerConfig);

如果开发者不想使用 CircuitBreakerRegistry 来管理断路器,那么也可以直接创建一个 CircuitBreaker 对象,创建方式如下:

 CircuitBreaker defaultCircuitBreaker = CircuitBreaker.ofDefaults("testName");
 CircuitBreaker customCircuitBreaker = CircuitBreaker.of("testName", circuitBreakerConfig);
断路器使用案例

断路器使用了装饰者模式,开发者可以使用 CircuitBreaker.decorateCheckedSupplier(), CircuitBreaker.decorateCheckedRunnable() 或者 CircuitBreaker.decorateCheckedFunction() 来装饰 Supplier / Runnable / Function 或者 CheckedRunnable / CheckedFunction,然后使用 Try.of(…​) 或者 Try.run(…​) 来进行调用操作,也可以使用 map、flatMap、filter、recover 或者 andThen 进行链式调用,但是调用这些方法断路器必须处于 CLOSED 或者 HALF_OPEN 状态。例如下面一个例子,创建一个断路器出来,首先装饰了一个函数,这个函数返回一段字符串,然后使用 Try.of 去执行,执行完后再进入到 map 中去执行。如果第一个函数正常执行第二个函数才会执行,如果第一个函数执行失败,那么 map 函数将不会执行。

 

posted @ 2020-09-11 23:21  codedot  阅读(1703)  评论(0编辑  收藏  举报