382 lines
11 KiB
Markdown
382 lines
11 KiB
Markdown
|
|
# Resilience4j 使用模板与文档
|
|||
|
|
|
|||
|
|
## 1. 概述
|
|||
|
|
Resilience4j 是一个轻量级的容错库,专为 Java 8+ 和函数式编程设计。它提供了断路器、限流、重试、舱壁隔离和超时控制等功能,帮助构建弹性和可靠的系统。
|
|||
|
|
|
|||
|
|
## 2. 配置文件示例
|
|||
|
|
|
|||
|
|
### 2.1 application.yml 配置
|
|||
|
|
```yaml
|
|||
|
|
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 层使用示例
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
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 层使用示例
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
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 的集成,可以监控各种指标:
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
# 启用 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,可以只引入以下依赖:
|
|||
|
|
|
|||
|
|
```xml
|
|||
|
|
<dependency>
|
|||
|
|
<groupId>io.github.resilience4j</groupId>
|
|||
|
|
<artifactId>resilience4j-spring-boot3</artifactId>
|
|||
|
|
<version>${resilience4j.version}</version>
|
|||
|
|
</dependency>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
如果需要更精细的控制,可以单独引入所需的模块:
|
|||
|
|
|
|||
|
|
```xml
|
|||
|
|
<!-- 核心模块 -->
|
|||
|
|
<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 版本。
|