Feign Retryer如何通过@Value读取配置文件的重试参数
实现方案
你当前代码的问题有两个:一是没有给重试参数字段绑定配置文件值,二是clone()方法里硬编码了固定参数,按以下步骤修改即可实现配置化。
步骤1:添加配置项
在application.properties中增加自定义配置:
# 最大重试次数 feign.retry.max-attempt=3 # 重试间隔,单位:毫秒 feign.retry.interval=2000
如果用application.yml,配置格式为:
feign: retry: max-attempt: 3 interval: 2000
步骤2:修改重试器代码
推荐用构造器注入的方式,依赖更明确,也能避免字段注入的空指针风险:
@Slf4j @Component public class FeignConnectionRetryer implements Retryer { private final int retryMaxAttempt; private final long retryInterval; private int attempt = 1; // 从配置文件读取参数,冒号后为默认值,配置缺失时用默认值启动 public FeignConnectionRetryer( @Value("${feign.retry.max-attempt:3}") int retryMaxAttempt, @Value("${feign.retry.interval:2000}") long retryInterval) { this.retryMaxAttempt = retryMaxAttempt; this.retryInterval = retryInterval; } @Override public void continueOrPropagate(RetryableException e) { log.info("Feign retry attempt {} due to {} ", attempt, e.getMessage()); if (attempt++ == retryMaxAttempt) { throw e; } try { Thread.sleep(retryInterval); } catch (InterruptedException ignored) { Thread.currentThread().interrupt(); } } @Override public Retryer clone() { // 直接复用当前实例已注入的配置参数,不再硬编码 return new FeignConnectionRetryer(this.retryMaxAttempt, this.retryInterval); } }
如果你想保留原来的无参构造和双参构造的结构,也可以用字段注入的方式:在
retryMaxAttempt和retryInterval字段上直接加@Value("${feign.retry.max-attempt:3}")和@Value("${feign.retry.interval:2000}")注解,然后把clone()方法里的硬编码3, 2000L换成this.retryMaxAttempt, this.retryInterval即可,效果一致。
原理说明
Spring启动时会创建FeignConnectionRetryer的单例Bean,完成配置值的注入。Feign发起调用时不会直接用这个单例Bean,而是调用clone()方法生成全新的重试器实例,每个实例独立维护自己的attempt重试计数,不会出现线程安全问题。我们只需要在clone时把单例Bean中已经加载好的配置值传入新实例,就可以完全替换硬编码,后续调整重试参数只需要改配置文件,不需要重新编译代码。
内容的提问来源于stack exchange,提问作者Khaled Abusair
相关产品推荐
相关产品推荐

