You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 03:16:11