1. 概述

本文将介绍 Resilience4j 这个轻量级容错库。

核心价值:它帮助我们在微服务或分布式系统中,优雅地处理远程调用的故障,提升系统的弹性和稳定性。

虽然它灵感来源于 Hystrix,但相比后者,Resilience4j 更现代、API 更简洁,并且模块化设计优秀。更重要的是,它不依赖于 Netflix 的技术栈,更适合当前主流的 Spring Boot 2+ 和函数式编程风格。

它提供了多个独立可插拔的模块,常见的包括:

  • Circuit Breaker(熔断器):防止雪崩
  • Rate Limiter(限流器):控制请求频率
  • Bulkhead(舱壁):限制并发数
  • Retry(重试):自动重试失败请求
  • TimeLimiter(超时控制):限制调用耗时
  • Cache(缓存):结果缓存
  • ✅ 丰富的生态集成(Spring Boot、Retrofit 等)

每个模块都可以单独引入,按需使用,避免不必要的依赖膨胀。


2. Maven 依赖配置

使用前需引入对应模块的依赖。以 Circuit Breaker 为例:

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

📌 所有模块均可在 Maven Central 查到最新版本。

后续章节将依次介绍各常用模块的使用方式。


3. 熔断器(Circuit Breaker)

需引入 resilience4j-circuitbreaker

熔断机制是防止级联故障的核心手段。当某个远程服务持续失败时,熔断器会“跳闸”,直接拒绝后续请求一段时间,避免资源被耗尽。

基本用法

先定义配置,可使用默认值或自定义:

// 使用默认配置
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults();

// 或自定义配置:失败率超过 20%,且至少有 5 次调用记录时触发熔断
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
  .failureRateThreshold(20)
  .slidingWindowType(SlidingWindowType.COUNT_BASED)
  .slidingWindowSize(5)
  .build();

创建熔断器并装饰目标方法:

interface RemoteService {
    int process(int i);
}

CircuitBreakerRegistry registry = CircuitBreakerRegistry.of(config);
CircuitBreaker circuitBreaker = registry.circuitBreaker("myService");

// 装饰函数,使其受熔断保护
Function<Integer, Integer> decorated = CircuitBreaker
  .decorateFunction(circuitBreaker, service::process);

验证行为

通过测试验证熔断逻辑是否生效:

// 模拟服务始终抛异常
when(service.process(any(Integer.class))).thenThrow(new RuntimeException());

for (int i = 0; i < 10; i++) {
    try {
        decorated.apply(i);
    } catch (Exception ignore) {}
}

// 验证:只尝试了 5 次就熔断了,后续请求被短路
verify(service, times(5)).process(any(Integer.class));

3.1 熔断器状态与关键配置

熔断器有三种状态:

状态 说明
CLOSED 正常状态,请求正常放行
OPEN 熔断开启,所有请求直接失败(短路)
HALF_OPEN 半开状态,尝试放行少量请求探测服务是否恢复

可配置的关键参数包括:

  • 🔧 failureRateThreshold:触发熔断的失败率阈值(如 50%)
  • 🔧 waitDurationInOpenState:熔断后保持 OPEN 的时间(如 30s 后进入 HALF_OPEN)
  • 🔧 slidingWindowSize:滑动窗口大小,用于统计失败率
  • 🔧 recordExceptions / ignoreExceptions:指定哪些异常计入失败
  • 🎯 eventConsumer:监听熔断事件(如日志、告警)

⚠️ 踩坑提示:默认情况下 Exception 不会被视为失败,需显式配置 recordException(Exception.class) 才能捕获。


4. 限流器(Rate Limiter)

需引入 resilience4j-ratelimiter

顾名思义,用于限制单位时间内允许的请求数量,常用于保护下游服务不被突发流量打垮。

示例代码

// 每 1 秒最多允许 2 次调用
RateLimiterConfig config = RateLimiterConfig.custom()
  .limitForPeriod(2)
  .limitRefreshPeriod(Duration.ofSeconds(1))
  .timeoutDuration(Duration.ofMillis(100))
  .build();

RateLimiterRegistry registry = RateLimiterRegistry.of(config);
RateLimiter rateLimiter = registry.rateLimiter("myRateLimiter");

Function<Integer, Integer> decorated = RateLimiter
  .decorateFunction(rateLimiter, service::process);

关键配置项

  • limitForPeriod:每个周期允许的请求数
  • limitRefreshPeriod:限流周期(如 1s)
  • timeoutDuration:线程等待获取许可的最大时间,超时报错
  • eventConsumer:可监听限流事件

✅ 简单粗暴理解:就像给接口加了个“令牌桶”,没令牌就得等或拒绝。


5. 舱壁(Bulkhead)

需引入 resilience4j-bulkhead

限制对某服务的最大并发调用数,防止某个慢接口耗尽整个应用的线程池资源。

示例:限制并发为 1

BulkheadConfig config = BulkheadConfig.custom()
  .maxConcurrentCalls(1)
  .maxWaitDuration(Duration.ofMillis(10))
  .build();

BulkheadRegistry registry = BulkheadRegistry.of(config);
Bulkhead bulkhead = registry.bulkhead("myBulkhead");

Function<Integer, Integer> decorated = Bulkhead
  .decorateFunction(bulkhead, service::process);

测试并发控制

CountDownLatch latch = new CountDownLatch(1);

// 模拟服务长时间运行
when(service.process(anyInt())).thenAnswer(invocation -> {
    latch.countDown();
    Thread.currentThread().join(); // 永久阻塞
    return null;
});

// 提交第一个任务
ForkJoinTask<?> task = ForkJoinPool.commonPool().submit(() -> {
    try {
        decorated.apply(1);
    } finally {
        bulkhead.onComplete(); // 手动释放
    }
});

latch.await(); // 等待第一个任务进入执行

// 尝试获取许可 → 应该失败(已被占用)
assertThat(bulkhead.tryAcquirePermission()).isFalse();

配置说明

  • maxConcurrentCalls:最大并发数
  • maxWaitDuration:等待获取许可的最长时间,超时抛异常

⚠️ 注意:onComplete() 必须在 finally 中调用,否则许可不会释放!


6. 重试(Retry)

需引入 resilience4j-retry

对临时性故障(如网络抖动)自动重试,提升调用成功率。

基本用法

RetryConfig config = RetryConfig.custom()
  .maxAttempts(2) // 最多重试 1 次(共 2 次尝试)
  .waitDuration(Duration.ofMillis(100))
  .retryExceptions(IOException.class) // 只对特定异常重试
  .build();

RetryRegistry registry = RetryRegistry.of(config);
Retry retry = registry.retry("myRetry");

Function<Integer, Void> decorated = Retry.decorateFunction(retry, (Integer s) -> {
    service.process(s);
    return null;
});

验证重试逻辑

when(service.process(anyInt())).thenThrow(new RuntimeException());

try {
    decorated.apply(1);
    fail("Expected an exception after retries exhausted");
} catch (Exception e) {
    // 验证:总共调用了 2 次(初始 + 1 次重试)
    verify(service, times(2)).process(any(Integer.class));
}

可配置项

  • maxAttempts:最大尝试次数
  • waitDuration:每次重试间隔
  • intervalFunction:可实现指数退避(如 IntervalFunction.ofExponentialBackoff()
  • retryExceptions / ignoreExceptions:控制重试触发条件

7. 缓存(Cache)

需引入 resilience4j-cache

基于 JSR-107(JCache)标准实现调用结果缓存,避免重复请求。

使用示例

javax.cache.Cache<Integer, Integer> cache = Caffeine.newBuilder()
  .build(); // 实际项目可用 Caffeine、Ehcache 等

Cache<Integer, Integer> cacheContext = Cache.of(cache);

// 注意:仅支持 Supplier / Callable
Supplier<Integer> cachedSupplier = Cache.decorateSupplier(cacheContext, () -> service.process(1));

// 第一次执行真实调用,结果存入缓存
Integer result1 = cachedSupplier.get();

// 第二次直接从缓存返回
Integer result2 = cachedSupplier.get();

⚠️ 注意:该模块不提供 decorateFunction 方法,只能装饰 SupplierCallable


8. 超时控制(TimeLimiter)

需引入 resilience4j-timelimiter

限制远程调用的执行时间,避免长时间阻塞线程。

示例:设置 1ms 超时

TimeLimiterConfig config = TimeLimiterConfig.custom()
  .timeoutDuration(Duration.ofMillis(1))
  .build();

TimeLimiter timeLimiter = TimeLimiter.of(config);

验证超时行为

Future<?> futureMock = mock(Future.class);
Callable<Object> restrictedCall = TimeLimiter
  .decorateFutureSupplier(timeLimiter, () -> futureMock);

restrictedCall.call();

// 验证:Future.get() 被传入了 1ms 超时参数
verify(futureMock).get(1, TimeUnit.MILLISECONDS);

与其他模块组合使用

常与 CircuitBreaker 联用,避免因超时导致熔断器误判:

Callable<Object> chainedCallable = CircuitBreaker
  .decorateCallable(circuitBreaker, restrictedCall);

9. 扩展模块(Add-on Modules)

Resilience4j 提供了丰富的框架集成模块,简化配置和使用:

框架 模块
Spring Boot resilience4j-spring-boot2
Ratpack resilience4j-ratpack
Retrofit resilience4j-retrofit
Vert.x resilience4j-vertx
Dropwizard resilience4j-metrics
Prometheus resilience4j-prometheus

✅ 推荐:在 Spring Boot 项目中直接使用 resilience4j-spring-boot2,可通过 YAML 配置所有策略,无需手写代码。


10. 总结

Resilience4j 是一个现代、轻量、函数式风格的容错库,相比 Hystrix 更适合当前技术栈。

📌 核心优势:

  • 模块化设计,按需引入
  • 函数式 API,易于组合
  • 与主流框架无缝集成
  • 无反射依赖,性能好

在构建高可用微服务时,合理使用 Circuit Breaker、Rate Limiter、Bulkhead 等策略,能显著提升系统稳定性。

示例代码已托管至 GitHub:https://github.com/resilience4j/resilience4j-examples


原始标题:Guide to Resilience4j