Spring Boot中为不同异常配置Resilience4J多重试策略的方法
问题描述
在Spring Boot项目中使用Resilience4J提升服务韧性时,需要针对不同异常设置差异化重试策略:
- 针对
RequestNotPermitted(限流触发)设置10次重试 - 针对
HttpServerErrorException(远程服务错误)保持2次重试
尝试添加第二个@Retry注解时,因该注解不支持重复标注导致编译失败,现需符合规范的可行解决方案。
原服务代码
@Service class SomeService { @RateLimiter(name = "rateLimiter") @Retry(name = "retryTwice", fallbackMethod = "fallback") void doSomethingImportant(int id) { // 核心业务逻辑 } void fallback(int id, Throwable throwable) { // 降级逻辑 } }
原配置(application.yml)
resilience4j.retry: instances: retryTwice: maxAttempts: 2 retryExceptions: - org.springframework.web.client.HttpServerErrorException # 远程服务问题 - io.github.resilience4j.ratelimiter.RequestNotPermitted # 触发限流 resilience4j.ratelimiter: limiters: rateLimiter: limitForPeriod: 1 limitRefreshPeriod: 1s timeoutDuration: 3s
错误尝试代码(无法编译)
@Service class SomeService { @RateLimiter(name = "rateLimiter") @Retry(name = "retryTwice", fallbackMethod = "fallback") @Retry(name = "retryTenTimes", fallbackMethod = "fallback") void doSomethingImportant(int id) { // 核心业务逻辑 } void fallback(int id, Throwable throwable) { // 降级逻辑 } }
对应配置更新
resilience4j.retry: instances: retryTwice: maxAttempts: 2 retryExceptions: - org.springframework.web.client.HttpServerErrorException # 远程服务问题 retryTenTimes: maxAttempts: 10 retryExceptions: - io.github.resilience4j.ratelimiter.RequestNotPermitted # 触发限流 resilience4j.ratelimiter: limiters: rateLimiter: limitForPeriod: 1 limitRefreshPeriod: 1s timeoutDuration: 3s
可行解决方案
方案1:编程式Retry API(灵活可控)
通过Resilience4J编程式API手动嵌套重试逻辑,分别处理不同异常的重试策略,避开注解重复限制。
修改后服务代码
@Service class SomeService { private final Retry retryTwice; private final Retry retryTenTimes; private final RateLimiter rateLimiter; // 注入RetryRegistry和RateLimiterRegistry public SomeService(RetryRegistry retryRegistry, RateLimiterRegistry rateLimiterRegistry) { this.retryTwice = retryRegistry.retry("retryTwice"); this.retryTenTimes = retryRegistry.retry("retryTenTimes"); this.rateLimiter = rateLimiterRegistry.rateLimiter("rateLimiter"); } void doSomethingImportant(int id) { // 外层:处理RequestNotPermitted的10次重试 CheckedRunnable rateLimitedRetry = Retry.decorateCheckedRunnable(retryTenTimes, () -> { // 中层:限流控制 RateLimiter.decorateCheckedRunnable(rateLimiter, () -> { // 内层:处理HttpServerErrorException的2次重试 Retry.decorateCheckedRunnable(retryTwice, () -> { // 核心业务逻辑 }).run(); }).run(); }); try { rateLimitedRetry.run(); } catch (Throwable throwable) { fallback(id, throwable); } } void fallback(int id, Throwable throwable) { // 降级逻辑 } }
配置保持更新后的yaml不变
方案2:方法拆分分层处理
将业务逻辑拆分为多层,通过方法嵌套实现不同异常的重试控制,外层处理限流异常重试,内层处理服务错误重试。
修改后服务代码
@Service class SomeService { @RateLimiter(name = "rateLimiter") @Retry(name = "retryTenTimes", fallbackMethod = "fallback") void doSomethingImportant(int id) { doCoreBusiness(id); } @Retry(name = "retryTwice", fallbackMethod = "coreFallback") void doCoreBusiness(int id) { // 核心业务逻辑 } void coreFallback(int id, Throwable throwable) { // 内层重试失败后抛出异常,触发外层重试 throw new RuntimeException(throwable); } void fallback(int id, Throwable throwable) { // 最终降级逻辑 } }
配置保持更新后的yaml不变
方案3:单Retry实例自定义异常规则(Resilience4J ≥1.7.0)
通过exceptionPredicate属性在单个Retry实例中为不同异常设置差异化重试次数,无需拆分方法或使用编程式API。
修改配置(application.yml)
resilience4j.retry: instances: customRetry: maxAttempts: 10 # 默认最大重试次数 retryExceptions: - org.springframework.web.client.HttpServerErrorException - io.github.resilience4j.ratelimiter.RequestNotPermitted # 针对特定异常覆盖重试次数 exceptionPredicate: - exceptionType: org.springframework.web.client.HttpServerErrorException maxAttempts: 2 resilience4j.ratelimiter: limiters: rateLimiter: limitForPeriod: 1 limitRefreshPeriod: 1s timeoutDuration: 3s
修改后服务代码
@Service class SomeService { @RateLimiter(name = "rateLimiter") @Retry(name = "customRetry", fallbackMethod = "fallback") void doSomethingImportant(int id) { // 核心业务逻辑 } void fallback(int id, Throwable throwable) { // 降级逻辑 } }
内容的提问来源于stack exchange,提问作者matsev
相关产品推荐
相关产品推荐

