tacit/resilience4j-usage-template.md

11 KiB
Raw Permalink Blame History

Resilience4j 使用模板与文档

1. 概述

Resilience4j 是一个轻量级的容错库,专为 Java 8+ 和函数式编程设计。它提供了断路器、限流、重试、舱壁隔离和超时控制等功能,帮助构建弹性和可靠的系统。

2. 配置文件示例

2.1 application.yml 配置

resilience4j:
  # 断路器配置
  circuitbreaker:
    instances:
      userServiceCircuitBreaker:
        # 失败阈值百分比
        failureRateThreshold: 50
        # 滑动窗口类型count-based 或 time-based
        slidingWindowType: COUNT_BASED
        # 滑动窗口大小
        slidingWindowSize: 10
        # 最小请求数
        minimumNumberOfCalls: 5
        # 半开状态下允许的最大请求数
        permittedNumberOfCallsInHalfOpenState: 3
        # 等待时间(毫秒)
        waitDurationInOpenState: 10000
        # 自动从半开状态恢复到关闭状态
        automaticTransitionFromOpenToHalfOpenEnabled: true
        # 忽略的异常类型
        ignoreExceptions:
          - org.springframework.web.client.HttpClientErrorException$BadRequest

  # 限流配置
  ratelimiter:
    instances:
      userServiceRateLimiter:
        # 每秒允许的请求数
        limitForPeriod: 100
        # 时间窗口(毫秒)
        limitRefreshPeriod: 1000
        # 等待获取许可的超时时间(毫秒)
        timeoutDuration: 500

  # 重试配置
  retry:
    instances:
      userServiceRetry:
        # 最大重试次数
        maxAttempts: 3
        # 初始重试间隔(毫秒)
        waitDuration: 1000
        # 重试退避策略
        retryExponentialBackoff:
          initialInterval: 1000
          multiplier: 2
          maxInterval: 10000
        # 重试的异常类型
        retryExceptions:
          - org.springframework.web.client.HttpServerErrorException
        # 忽略的异常类型
        ignoreExceptions:
          - org.springframework.web.client.HttpClientErrorException$BadRequest

  # 舱壁配置
  bulkhead:
    instances:
      userServiceBulkhead:
        # 最大并行执行的任务数
        maxConcurrentCalls: 20
        # 等待队列大小
        maxWaitDuration: 1000

  # 超时控制配置
  timelimiter:
    instances:
      userServiceTimeLimiter:
        # 超时时间(毫秒)
        timeoutDuration: 3000

3. 使用示例

3.1 Service 层使用示例

package com.tacit.admin.service.impl;

import io.github.resilience4j.bulkhead.annotation.Bulkhead;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import io.github.resilience4j.retry.annotation.Retry;
import io.github.resilience4j.timelimiter.annotation.TimeLimiter;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.concurrent.CompletableFuture;

@Service
public class UserService {

    private final RestTemplate restTemplate;

    public UserService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    /**
     * 使用断路器示例
     * @param userId 用户ID
     * @return 用户信息
     */
    @CircuitBreaker(
            name = "userServiceCircuitBreaker",
            fallbackMethod = "getUserFallback"
    )
    public String getUserById(Long userId) {
        return restTemplate.getForObject("http://user-service/users/{id}", String.class, userId);
    }

    /**
     * 使用限流示例
     * @param userId 用户ID
     * @return 用户信息
     */
    @RateLimiter(
            name = "userServiceRateLimiter",
            fallbackMethod = "getUserFallback"
    )
    public String getUserWithRateLimit(Long userId) {
        return restTemplate.getForObject("http://user-service/users/{id}", String.class, userId);
    }

    /**
     * 使用重试示例
     * @param userId 用户ID
     * @return 用户信息
     */
    @Retry(
            name = "userServiceRetry",
            fallbackMethod = "getUserFallback"
    )
    public String getUserWithRetry(Long userId) {
        return restTemplate.getForObject("http://user-service/users/{id}", String.class, userId);
    }

    /**
     * 使用舱壁示例
     * @param userId 用户ID
     * @return 用户信息
     */
    @Bulkhead(
            name = "userServiceBulkhead",
            fallbackMethod = "getUserFallback"
    )
    public String getUserWithBulkhead(Long userId) {
        return restTemplate.getForObject("http://user-service/users/{id}", String.class, userId);
    }

    /**
     * 使用超时控制示例
     * @param userId 用户ID
     * @return 用户信息
     */
    @TimeLimiter(
            name = "userServiceTimeLimiter",
            fallbackMethod = "getUserAsyncFallback"
    )
    public CompletableFuture<String> getUserWithTimeout(Long userId) {
        return CompletableFuture.supplyAsync(() -> 
            restTemplate.getForObject("http://user-service/users/{id}", String.class, userId)
        );
    }

    /**
     * 组合使用多个功能示例
     * @param userId 用户ID
     * @return 用户信息
     */
    @CircuitBreaker(
            name = "userServiceCircuitBreaker",
            fallbackMethod = "getUserFallback"
    )
    @Retry(
            name = "userServiceRetry"
    )
    @RateLimiter(
            name = "userServiceRateLimiter"
    )
    public String getUserWithMultipleFeatures(Long userId) {
        return restTemplate.getForObject("http://user-service/users/{id}", String.class, userId);
    }

    /**
     * 同步回退方法
     * @param userId 用户ID
     * @param ex 异常
     * @return 回退结果
     */
    private String getUserFallback(Long userId, Exception ex) {
        return "{\"id\":0,\"name\":\"Fallback User\",\"message\":\"服务暂时不可用,请稍后重试\"}";
    }

    /**
     * 异步回退方法
     * @param userId 用户ID
     * @param ex 异常
     * @return 回退结果
     */
    private CompletableFuture<String> getUserAsyncFallback(Long userId, Exception ex) {
        return CompletableFuture.completedFuture(
            "{\"id\":0,\"name\":\"Async Fallback User\",\"message\":\"服务暂时不可用,请稍后重试\"}"
        );
    }
}

3.2 Controller 层使用示例

package com.tacit.admin.controller;

import com.tacit.admin.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.CompletableFuture;

@RestController
@RequestMapping("/user")
@Tag(name = "用户管理", description = "用户管理相关接口")
public class UserController {

    @Autowired
    private UserService userService;

    @Operation(summary = "获取用户信息", description = "使用断路器模式获取用户信息")
    @GetMapping("/get/{id}")
    public String getUser(@PathVariable Long id) {
        return userService.getUserById(id);
    }

    @Operation(summary = "限流获取用户信息", description = "使用限流模式获取用户信息")
    @GetMapping("/rate-limit/{id}")
    public String getUserWithRateLimit(@PathVariable Long id) {
        return userService.getUserWithRateLimit(id);
    }

    @Operation(summary = "重试获取用户信息", description = "使用重试模式获取用户信息")
    @GetMapping("/retry/{id}")
    public String getUserWithRetry(@PathVariable Long id) {
        return userService.getUserWithRetry(id);
    }

    @Operation(summary = "超时控制获取用户信息", description = "使用超时控制获取用户信息")
    @GetMapping("/timeout/{id}")
    public CompletableFuture<String> getUserWithTimeout(@PathVariable Long id) {
        return userService.getUserWithTimeout(id);
    }

    @Operation(summary = "组合功能获取用户信息", description = "组合使用多个容错功能获取用户信息")
    @GetMapping("/multiple/{id}")
    public String getUserWithMultipleFeatures(@PathVariable Long id) {
        return userService.getUserWithMultipleFeatures(id);
    }
}

4. 使用说明

4.1 注解说明

注解 功能 主要属性
@CircuitBreaker 断路器 name, fallbackMethod
@RateLimiter 限流 name, fallbackMethod
@Retry 重试 name, fallbackMethod
@Bulkhead 舱壁隔离 name, fallbackMethod, type
@TimeLimiter 超时控制 name, fallbackMethod

4.2 回退方法注意事项

  1. 回退方法必须与原始方法在同一个类中
  2. 回退方法的参数列表必须与原始方法相同,并且最后一个参数是 Throwable 类型
  3. 回退方法的返回类型必须与原始方法相同
  4. 异步方法的回退方法必须返回 CompletableFuture

4.3 监控与指标

Resilience4j 提供了与 Micrometer 和 Prometheus 的集成,可以监控各种指标:

# 启用 Resilience4j 指标management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
  endpoint:
    health:
      show-details: always
  metrics:
    export:
      prometheus:
        enabled: true

5. 最佳实践

  1. 合理配置参数:根据实际业务场景调整各功能的参数
  2. 使用回退策略:为每个容错功能提供适当的回退方法
  3. 监控与告警:定期监控各功能的指标,设置合理的告警阈值
  4. 组合使用:根据需求组合使用多个容错功能
  5. 异常处理:区分可重试和不可重试的异常类型
  6. 性能测试:在生产环境部署前进行充分的性能测试

6. 常见问题与解决方案

6.1 断路器一直处于打开状态

  • 检查失败率阈值是否设置过低
  • 检查是否有足够的请求数触发断路器
  • 检查忽略的异常类型是否正确

6.2 限流不生效

  • 检查限流配置是否正确
  • 检查限流实例名称是否与注解中的名称一致
  • 检查是否有其他限流机制影响

6.3 重试不生效

  • 检查重试的异常类型是否正确
  • 检查重试次数和间隔是否合理
  • 检查是否有其他重试机制影响

7. 依赖管理

如果使用 Spring Boot可以只引入以下依赖

<dependency>
    <groupId>io.github.resilience4j</groupId>
    <artifactId>resilience4j-spring-boot3</artifactId>
    <version>${resilience4j.version}</version>
</dependency>

如果需要更精细的控制,可以单独引入所需的模块:

<!-- 核心模块 -->
<dependency>
    <groupId>io.github.resilience4j</groupId>
    <artifactId>resilience4j-core</artifactId>
    <version>${resilience4j.version}</version>
</dependency>

<!-- 各功能模块 -->
<dependency>
    <groupId>io.github.resilience4j</groupId>
    <artifactId>resilience4j-circuitbreaker</artifactId>
    <version>${resilience4j.version}</version>
</dependency>

<dependency>
    <groupId>io.github.resilience4j</groupId>
    <artifactId>resilience4j-ratelimiter</artifactId>
    <version>${resilience4j.version}</version>
</dependency>

<!-- 其他模块... -->

8. 版本兼容

Resilience4j 版本 Spring Boot 版本 Java 版本
2.x 3.x 17+
1.x 2.x 8+

请根据您的 Spring Boot 版本选择合适的 Resilience4j 版本。