在现代分布式系统中,服务之间的调用可能会因为网络延迟、超时或服务不可用等原因而失败。为了提高系统的稳定性和可用性,我们需要引入容错机制。Resilience4j 是一个轻量级的容错库,专为 Java 8 和函数式编程设计,提供了诸如断路器(Circuit Breaker)、重试(Retry)、限流(Rate Limiter)等特性。
首先,在 pom.xml
中添加 Resilience4j 的依赖:
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
<version>1.7.1</version>
</dependency>
在 application.yml
中配置断路器参数:
resilience4j.circuitbreaker:
instances:
backendA:
registerHealthIndicator: true
slidingWindowSize: 10
minimumNumberOfCalls: 5
permittedNumberOfCallsInHalfOpenState: 3
automaticTransitionFromOpenToHalfOpenEnabled: true
waitDurationInOpenState: 10s
failureRateThreshold: 50
recordExceptions:
- java.io.IOException
- org.springframework.web.client.HttpServerErrorException
ignoreExceptions:
- java.lang.IllegalArgumentException
创建一个简单的服务类,并使用 Resilience4j 提供的注解来保护方法。
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import org.springframework.stereotype.Service;
@Service
public class BackendService {
@CircuitBreaker(name = "backendA", fallbackMethod = "fallback")
public String callBackendService() {
// 模拟后端服务调用
if (Math.random() < 0.5) {
throw new RuntimeException("Simulated backend failure");
}
return "Success";
}
public String fallback(RuntimeException ex) {
return "Fallback response due to: " + ex.getMessage();
}
}
启动应用并多次调用 callBackendService()
方法。如果后端服务失败次数达到配置中的阈值,断路器将切换到打开状态,后续调用将直接返回回退响应。
同样可以在 application.yml
中配置重试参数:
resilience4j.retry:
instances:
backendA:
maxAttempts: 3
waitDuration: 1s
retryExceptions:
- java.io.IOException
- org.springframework.web.client.HttpServerErrorException
ignoreExceptions:
- java.lang.IllegalArgumentException
然后在代码中使用 @Retry
注解:
import io.github.resilience4j.retry.annotation.Retry;
@Service
public class BackendService {
@Retry(name = "backendA", fallbackMethod = "retryFallback")
public String callBackendServiceWithRetry() {
if (Math.random() < 0.5) {
throw new IOException("Simulated backend failure");
}
return "Success with Retry";
}
public String retryFallback(IOException ex) {
return "Retry Fallback response due to: " + ex.getMessage();
}
}
配置限流参数:
resilience4j.ratelimiter:
instances:
backendA:
limitForPeriod: 5
limitRefreshPeriod: 1s
timeoutDuration: 1s
使用 @RateLimiter
注解:
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
@Service
public class BackendService {
@RateLimiter(name = "backendA", fallbackMethod = "rateLimitFallback")
public String callBackendServiceWithRateLimit() {
return "Success with Rate Limit";
}
public String rateLimitFallback(CallNotPermittedException ex) {
return "Rate Limit Fallback response due to: " + ex.getMessage();
}
}