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

Spring Boot微服务中Resilience4j熔断与重试共存时重试失效问题

Resilience4j CircuitBreaker与Retry共存时重试不生效的解决方案

问题场景

在基于Spring Boot的微服务项目中,两个微服务通过API网关交互,尝试用Resilience4j同时实现熔断和重试机制,但发现添加@CircuitBreaker注解后重试逻辑完全不执行,移除该注解后重试功能恢复正常。

服务层核心代码

@Override
@CircuitBreaker(name="${spring.application.name}", fallbackMethod = "getDefaultDepartment")
@Retry(name="${spring.application.name}", fallbackMethod = "getDefaultDepartment")
public ResponseDto getEmployee(Long id) {
    LOGGER.info("inside getEmployee by ID method");
    Employee employee = employeeRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("Employee", "id", id));
    
    // OpenFeign调用其他微服务
    DepartmentDto departmentDto = apiClient.getDepartment(employee.getDepartmentCode());

    return new ResponseDto(modelMapper.map(employee, EmployeeDto.class), departmentDto);
}

配置文件内容

#------------------------------  Circuit breaker properties--------------------------------------
resilience4j.circuitbreaker.instances.EMPLOYEE-SERVICE.registerHealthIndicator=true
resilience4j.circuitbreaker.instances.EMPLOYEE-SERVICE.failureRateThreshold=50
resilience4j.circuitbreaker.instances.EMPLOYEE-SERVICE.minimumNumberOfCalls=5
resilience4j.circuitbreaker.instances.EMPLOYEE-SERVICE.automaticTransitionFromOpenToHalfOpenEnabled=true
resilience4j.circuitbreaker.instances.EMPLOYEE-SERVICE.waitDurationInOpenState=5s
resilience4j.circuitbreaker.instances.EMPLOYEE-SERVICE.permittedNumberOfCallsInHalfOpenState=3
resilience4j.circuitbreaker.instances.EMPLOYEE-SERVICE.slidingWindowSize=10
resilience4j.circuitbreaker.instances.EMPLOYEE-SERVICE.slidingWindowType=COUNT_BASED


#------------------------------  Retry Configuration  --------------------------------------
resilience4j.retry.instances.EMPLOYEE-SERVICE.registerHealthIndicator=true
resilience4j.retry.instances.EMPLOYEE-SERVICE.maxAttempts=10
resilience4j.retry.instances.EMPLOYEE-SERVICE.waitDuration=1s

原因分析

Resilience4j的注解基于Spring AOP实现,默认情况下@CircuitBreaker的AOP优先级高于@Retry。这意味着熔断的代理逻辑会包裹重试的代理逻辑:当调用失败时,熔断会第一时间捕获异常并触发fallback,根本不会进入重试的逻辑分支。

解决方案

1. 调整注解顺序(最简单有效)

将@Retry注解放在@CircuitBreaker上方,让重试的代理包裹熔断的代理。这样调用失败时会先执行重试逻辑,重试耗尽后再触发熔断:

@Override
@Retry(name="${spring.application.name}", fallbackMethod = "getDefaultDepartment")
@CircuitBreaker(name="${spring.application.name}", fallbackMethod = "getDefaultDepartment")
public ResponseDto getEmployee(Long id) {
    // 原有逻辑不变
}

2. 自定义AOP优先级(灵活控制)

如果需要更精细的优先级控制,可以通过配置类指定Retry和CircuitBreaker的AOP顺序,确保Retry的优先级更高:

import io.github.resilience4j.circuitbreaker.CircuitBreakerAspect;
import io.github.resilience4j.retry.RetryAspect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;

@Configuration
public class Resilience4jConfig {

    @Bean
    public RetryAspect retryAspect() {
        RetryAspect aspect = new RetryAspect();
        aspect.setOrder(Ordered.HIGHEST_PRECEDENCE); // 最高优先级
        return aspect;
    }

    @Bean
    public CircuitBreakerAspect circuitBreakerAspect() {
        CircuitBreakerAspect aspect = new CircuitBreakerAspect();
        aspect.setOrder(Ordered.HIGHEST_PRECEDENCE + 1); // 优先级低于Retry
        return aspect;
    }
}

3. 确保重试捕获目标异常

默认情况下,Resilience4j Retry只会重试RuntimeException类型的异常。如果Feign调用抛出的FeignException或自定义异常(如ResourceNotFoundException)需要被重试,需在配置中明确指定:

resilience4j.retry.instances.EMPLOYEE-SERVICE.retry-exceptions=com.example.ResourceNotFoundException,feign.FeignException

4. 统一fallback逻辑注意事项

两个注解共用同一个fallback方法时,需确保方法签名兼容:fallback方法需要接收原方法的参数+异常对象,示例如下:

public ResponseDto getDefaultDepartment(Long id, Throwable throwable) {
    // 降级逻辑实现
    EmployeeDto employeeDto = new EmployeeDto();
    DepartmentDto departmentDto = new DepartmentDto();
    departmentDto.setDepartmentName("Default Dept");
    departmentDto.setDepartmentCode("DEFAULT");
    return new ResponseDto(employeeDto, departmentDto);
}

内容的提问来源于stack exchange,提问作者Somesh Vemula

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 05:07:13