SpringBoot在@PostConstruct方法中调用FeignClient加载不到Hystrix配置问题
版本信息#
- spring-cloud-starter-openfeign:2.1.3.RELEASE
- spring-boot-starter-parent:2.2.2.RELEASE
问题描述#
- @Service类@Autowired了一个@FeignClient,在@PostConstruct方法中调用此@FeignClient的方法,会直接进入Fallback,怀疑配置的Hystrix超时timeoutInMilliseconds配置没有生效
配置&代码#
-
application. yml
hystrix: threadpool: default: coreSize: 30 maximumSize: 100 command: default: execution: isolation: thread: timeoutInMilliseconds: 9000 feign: hystrix: enabled: true httpclient: enabled: true client: config: default: connectTimeout: 3000 readTimeout: 5000
-
@FeignClient
@FeignClient(name = "dictionaryService", path = "internal/metrics", url = "${host}", decode404 = true, configuration = {ResponseDecoder.class}, fallback = DictionaryServiceFallback.class) public interface DictionaryService { @PostMapping("dictionary/getValueByPathKey") String getValueByPathKey(@RequestParam("path") String path, @RequestParam("key") String key); }
-
@Service
@Slf4j @Service public class RsaServiceImpl implements RsaEncService { @Autowired private DictionaryService dictionaryService; private static String PUBLIC_KEY = null; private static String PRIVATE_KEY = null; private static final String XAPI_TOKEN = "xapi.token"; @PostConstruct public void initKey() { PUBLIC_KEY = getPublicKey(); PRIVATE_KEY = getPrivateKey(); } @Override public String getPublicKey() { String value = dictionaryService.getValueByPathKey(XAPI_TOKEN, "public_key"); if (StringUtils.isBlank(value)) { log.error("PublicKey获取失败"); } return value; } @Override public String getPrivateKey() { String value = dictionaryService.getValueByPathKey(XAPI_TOKEN, "private_key"); if (StringUtils.isBlank(value)) { log.error("PrivateKey获取失败"); } return value; }
-
FallBack
@Slf4j @Component public class DictionaryServiceFallback implements DictionaryService { @Override public String getValueByPathKey(String path, String key) { log.error("获取字典失败 , path : {}, key : {}", path, key); return null; } }
原因分析#
- 怀疑是在@Service的Bean创建后,@PostConstruct方法调用时,还没有加载Hystrix的配置,所以Hystrix使用的默认配置(默认timeoutInMilliseconds为1s)
debug
到HystrixCommandProperties,发现没有加载到Hystrix的配置。而实际Hystrix配置应该通过ArchaiusAutoConfiguration中的Bean:ConfigurableEnvironmentConfiguration负责加载- @FeignClient是通过@EnableFeignClients注解扫描组装Bean得到的,HystrixCommand是在使用@FeignClient时才创建,通过feign.hystrix.HystrixInvocationHandler#invoke方法
- 在com.netflix.config.DynamicProperty#DynamicProperty(java.lang.String)构造函数中从ConcurrentCompositeConfiguration对象获取配置
解决#
-
使用@DependsOn("configurableEnvironmentConfiguration")注解
-
单独控制可以加在@Service注解上
@DependsOn("configurableEnvironmentConfiguration") @Slf4j @Service public class RsaServiceImpl implements RsaEncService { ...... }
-
全局控制加在Application启动类上
@DependsOn("configurableEnvironmentConfiguration") @SpringBootApplication public class DevApplication{ ...... }
-
总结#
- HystrixCommand是在首次调用@FeignClient才初始化,所以需要确定Hystrix的配置此时是否已经加载到
- Hystrix的配置默认是通过ArchaiusAutoConfiguration中的Bean--ConfigurableEnvironmentConfiguration负责加载
- 确保在使用@FeignClient时ConfigurableEnvironmentConfiguration已经被加载
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?