Resilience4j TimeLimiter配置对Spring Cloud OpenFeign读取超时是否生效?
我想确认Resilience4j配置中的resilience4j.timelimiter.instances.feignClienA.timeoutDuration是否对Spring Cloud OpenFeign的feignClienA的readTimeout生效。当前项目按配置设置后未生效,调试发现Feign通过feign.SynchronousMethodHandler#findOptions获取options参数设置readTimeout,但找不到该参数的注入位置,且resilience4j-feign的装饰器仅提供CircuitBreaker、Bulkhead,没有TimeLimiter。
当前配置与代码
YAML配置
## timeout resilience4j: timelimiter: instances: DataProcessFeignServiceprocessInitializeProcessTaskInitRequest: timeoutDuration: 240s cancel-running-future: true
Feign客户端代码
@FeignClient(value = "clearance-data-process-ib", fallbackFactory = DataProcessFeignServiceFallBack.class) public interface DataProcessFeignService { @PostMapping("/service/process-task/process-initialize") @Operation(method = "POST", summary = "initialize") ServerResponse<Boolean> processInitialize(@Valid @RequestBody ProcessTaskInitRequest request); }
测试代码
@GetMapping("/feignTest") public ApiResponse<String> feignTest() { ProcessTaskInitRequest request = new ProcessTaskInitRequest(); request.setDeclarationWaybillIdList(Lists.newArrayList("hello")); request.setTaskType("DATA_PRESS"); log.info("feignTest request:{}", JsonUtil.toJsonString(request)); dataProcessFeignService.processInitialize(request); return ApiResponse.success(); }
服务端代码(模拟长耗时)
@PostMapping("/process-initialize") @Operation(method = "POST", summary = "Initialize") public ServerResponse<Boolean> processInitialize(@Valid @RequestBody ProcessTaskInitRequest request) { try { TimeUnit.SECONDS.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } return ServerResponse.success(Boolean.TRUE); }
现象
预期请求在240秒时超时,但实际因Feign默认60秒超时,约60秒后触发降级。请问如何让Resilience4j的TimeLimiter配置生效?
要让Resilience4j的TimeLimiter配置生效,需要处理两个核心问题:屏蔽Feign自身的超时优先触发,以及给Feign客户端添加TimeLimiter装饰器,具体步骤如下:
1. 调整Feign的超时配置,使其大于Resilience4j TimeLimiter的时长
Feign默认的readTimeout是60秒,会先于Resilience4j的240秒超时触发,所以需要把Feign的超时调大(比如设为250秒),确保Resilience4j的TimeLimiter能先生效。
在YAML中添加Feign的超时配置:
feign: client: config: clearance-data-process-ib: # 对应FeignClient的value值 connectTimeout: 5000 # 连接超时,按需设置 readTimeout: 250000 # 读取超时设为250秒,大于240秒
如果是全局Feign配置,把clearance-data-process-ib换成default即可。
2. 给Feign客户端添加TimeLimiter装饰
resilience4j-feign默认只集成了CircuitBreaker和Bulkhead,需要手动配置让Feign使用TimeLimiter装饰器:
方式一:通过注解指定TimeLimiter
在Feign接口的方法上添加@TimeLimiter注解,指定对应的实例名:
@FeignClient(value = "clearance-data-process-ib", fallbackFactory = DataProcessFeignServiceFallBack.class) public interface DataProcessFeignService { @PostMapping("/service/process-task/process-initialize") @Operation(method = "POST", summary = "initialize") @TimeLimiter(name = "DataProcessFeignServiceprocessInitializeProcessTaskInitRequest") ServerResponse<Boolean> processInitialize(@Valid @RequestBody ProcessTaskInitRequest request); }
方式二:通过全局配置启用TimeLimiter装饰
如果需要给所有Feign客户端添加TimeLimiter,可以在配置类中自定义FeignBuilder:
@Configuration public class FeignResilience4jConfig { @Bean public Feign.Builder feignBuilder(TimeLimiterRegistry timeLimiterRegistry) { return Resilience4jFeign.builder() .timeLimiter(timeLimiterRegistry::getTimeLimiter) .circuitBreaker(CircuitBreaker.ofDefaults("default")); } }
这种方式下,每个Feign方法会自动匹配对应名称的TimeLimiter实例(规则是接口名+方法名+参数类型,和你当前配置的DataProcessFeignServiceprocessInitializeProcessTaskInitRequest一致)。
3. 验证配置生效
调整完成后,再次测试:请求会在240秒时触发Resilience4j的TimeLimiter超时,进而执行Feign的降级逻辑,而不是Feign默认的60秒超时。
内容的提问来源于stack exchange,提问作者luckyheng

