简介: feign是一个出色的Http请求客户端封装框架,feign-hystrix是整个框架体系里的其中一个模块,用来集成hystrix熔断器的,feign和hystrix这两个项目都是Netflix开源的(openfeign已独立迭代)。在spring boot项目中,可以使用spring-cloud-starter-openfeign模块,无缝集成feign和hystrix。但是,hystrix默认采用的Archaius来驱动hystrix的配置系统,无缝集成的同时,也会把archaius-core给引入进来。archaius是一个配置中心项目,类似spring cloud config

前言

feign是一个出色的Http请求客户端封装框架,feign-hystrix是整个框架体系里的其中一个模块,用来集成hystrix熔断器的,feign和hystrix这两个项目都是Netflix开源的(openfeign已独立迭代)。在spring boot项目中,可以使用spring-cloud-starter-openfeign模块,无缝集成feign和hystrix。但是,hystrix默认采用的Archaius来驱动hystrix的配置系统,无缝集成的同时,也会把archaius-core给引入进来。archaius是一个配置中心项目,类似spring cloud config和apollo,如果archaius只是作为hystrix配置的驱动,项目启动时会打印烦人的警告日志,提示你没有配置任何动态配置源。当项目里已经采用了apollo时,可以直接剔除掉Archaius,他们的功能定位高度重合了。直接剔除依赖,会导致原本配置在spring中的配置不生效,博主也是在不小心剔除后,遇到了配置不生效的问题,才有了本篇博文,记录下过程。只要稍加改动,结合apollo配置动态下发能力,可以做到hystrix的配置实时动态生效。

  • feign:https://github.com/OpenFeign/feign
  • hystrix:https://github.com/Netflix/Hystrix
  • archaius:https://github.com/Netflix/archaius
  • apollo:https://github.com/ctripcorp/apollo

archaius警告日志

2020-12-10 11:19:41.766 WARN 12835 --- [ main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources.2020-12-10 11:19:41.766 INFO 12835 --- [ main] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath.2020-12-10 11:19:41.772 WARN 12835 --- [ main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources.2020-12-10 11:19:41.772 INFO 12835 --- [ main] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath.

我们遇到的问题

在一次系统优化重构中,博主给整个项目来了一个360的大瘦身,把所有的未使用的依赖统统给挪走了。其中就包括了spring-cloud-starter-openfeign模块的archaius-core依赖。因为我们已经使用了apollo配置中心,archaius在这个项目里显得很多余,而且还会打印烦人的警告日志。所以就直接排除了,如:

implementation ('org.springframework.cloud:spring-cloud-starter-openfeign'){    exclude(module:"archaius-core")}

为此,专门了解了下archaius的来历,并且针对feign的熔断器的Fallback能力进行了测试,一切运行正常。上线一周后,问题暴露出来了,同事反馈,hystrix的配置好像不生效了。现象是,原本设置的hystrix线程执行不超时,却发生了很多执行一秒就超时了,我们的关键配置如下(这不是一个很好的配置示范,后面会调整更细粒度控制):

#禁止执行超时hystrix.command.default.execution.timeout.enabled = false

直观感觉就是这个配置不生效了,联想到archaius-core被移除,所以先立马恢复了依赖,重新打包上线,问题解决。就这?为了彻底搞清楚Hystrix的配置加载过程,我们对feign整合hystrix进行了全面的了解。

hystrix在feign中的加载过程

在spring-cloud-starter-openfeign的封装下,使用起来非常简单,但是内部的加载流程非常复杂。所以博主也不打算全面铺开来说这块内容,有机会会独立一篇来说。这里根据我们上文遇到的禁用执行超时不生效的问题,博主总结了加载流程中的几个关键的地方:
Feign和Hystrix的桥接器Feign-Hystrix

这个项目是feign和hystrix的桥接器,通过这样的一个桥接器,将两个框架的api能力整合在了一起,下面简要阐述下,加载过程关键类的作用:

  • SetterFactory:承载了构造HystrixCommand实例的所有的配置的接口,有一个默认实现Default,在下面会用到,是自定义配置实现的突破口
  • HystrixInvocationHandler:这是一个实现了JDK代理接口类,用来代理Feign最终的执行,HystrixCommand类就是在这个实例里被构造执行的,使用的构造方法正是带入参Setter的构造方法,集成方会实现SetterFactory来构造Setter。调试程序时我们将端点打进这个类里,就可以看到配置加载的情况

spring boot自动加载hystrix

@Configuration@ConditionalOnClass({ HystrixCommand.class, HystrixFeign.class })protected static class HystrixFeignConfiguration {   @Bean   @Scope("prototype")   @ConditionalOnMissingBean   @ConditionalOnProperty(name = "feign.hystrix.enabled")   public Feign.Builder feignHystrixBuilder() {      return HystrixFeign.builder();   }}

这里是Hystrix在feign框架下加载的总入口。这个默认的构建器Builder中,有一个默认实现的SetterFactory,这个SetterFactory专门负责传递参数给Hystrix初始化HystrixCommand用。可以看到这里Bean的实例化加上了@ConditionalOnMissingBean条件约束,即我们可以自定义实现Hystrix的构造器,覆盖这里的实现,在自定义的构造器中,可以通过自定义实现SetterFactory,来注入任意的配置。这个是实现Hystrix配置自定义加载的方式之一,不过不推荐,没必要破坏spirng现有的这种结构,而且代码也会比较冗长(下面{...}省略了一百多行配置处理代码,用来兼容Hystrix现有配置定义),看起来如下:

Hystrix的动态兜底配置

配置是hystrix的核心,各种策略的选择执行都需要配置来驱动,所以,虽然在应用层面不需要太多的配置设置,但是必要的配置hystrix都会填充一个默认值,比如,hystrix默认执行超时设置的1s。Hystrix中的配置有三个层次的加载优先级,如:

最先加载Setter:Setter是用户传递给Hystrix构造器的,所以优先级别最高
其次加载动态配置源:如果必要的配置在Setter里没有找到,则在动态配置源中获取
最后加载默认配置:如果动态配置源中也没有找到配置,则采用默认的配置
其中动态配置源,有一个基于SystemProperties的配置实现HystrixDynamicPropertiesSystemProperties。HystrixCommand在实例化时,如果用户没有给到具体的配置,Hystrix每次都会去SystemProperties中寻找配置。也就是说,我们可以通过-D参数注入任意Hystrix的配置参数,都会生效。有了这个特性,可以非常简单的结合apollo,达到hystrix配置动态生效的效果,而且所有配置兼容Hystrix原本的配置。

apollo配置驱动Hystrix

实现这个功能的关键是。系统初始化时,将hystrix.command前缀相关的配置从apollo中获取到然后统统注入SystemProperties。配置更新时,同时更新SystemProperties中的配置即可,非常简单,用代码说话:

/** * @author kl (http://kailing.pub) * @since 2020/12/10 */@Slf4j@Configuration@AutoConfigureBefore(value = {FeignClientsConfiguration.class, FeignAutoConfiguration.class})public class HystrixConfiguration{    public static final String DYNAMIC_TAG = "dynamic.";    public static final String DYNAMIC_PREFIX = DYNAMIC_TAG + "hystrix.command.";    public static final String PREFIX = "hystrix.command.";    @ApolloConfig    private Config config;    @PostConstruct    public void initHystrix(){        this.config.addChangeListener(                event -> this.loadHystrixConfig(event.changedKeys()),                null,                Sets.newHashSet(DYNAMIC_PREFIX)        );        this.loadHystrixConfig(config.getPropertyNames());    }    private void loadHystrixConfig(Set configkyes) {        configkyes.forEach(key -> {            if (StringUtils.containsIgnoreCase(key, PREFIX)) {                String value = config.getProperty(key, null);                String realKey = key.replaceAll(DYNAMIC_TAG,"").trim();                System.setProperty(realKey, value);                log.info("Hystrix config: {}={}", key, value);            }        });    }}

这里注意一个问题:为啥这里多设计了一个dynamic.前缀的配置,这是因为博主在测试过程中触发了apollo配置监听器隐藏的问题,导致Apollo的动态监听器不生效了。Apollo配置加载是以SystemProperties为最高优先级的,当配置发生变化时,apollo会将SystemProperties覆盖到配置之后,才比较本次配置发布是否有更新。因为我们一开始就将相关的配置加载到SystemProperties里了,所以每次变更都会被覆盖成之前的值,导致更新判断失效,一直进不了监听器。如果想要动态更新,就需要维护一份apollo的配置和SystemProperties里的映射关系,而不能保持一致,这样每次修改apollo时,就可以将维护映射关系的前缀去掉,然后将值动态更新到SystemProperties。目前的设计里,既支持原生的所有配置一次性加载,也支持dynamic.前缀拼装原有配置动态加载

配置示例

#初始化时一次性加载hystrix.command.default.execution.timeout.enabled = true#每次修改动态生效dynamic.hystrix.command.default.execution.timeout.enabled = true

结语

Feign-hystrix的配置,有了Apollo,还用Archaius吗?当然不用,采用apollo实现方案,既兼容了所有原生配置,还可以做到动态生效,岂不美哉。

原文:https://developer.aliyun.com/article/779849?spm=5176.8068049.0.0.39926d19wq2fv2&groupCode=othertech

apollo @value没生效_有Apollo,还用Archaius吗?相关推荐

  1. apollo @value没生效_不问不要紧,一文要人命,绝对的面试加分项配置中心Apollo深度解读...

    往期推荐 阿里面试官问我:到底知不知道什么是Eureka,这次,我没沉默 万字详解Ribbon架构,针对面试高频题多角度细说Ribbon 什么是Hystrix,阿里技术最终面,遗憾的倒在Hystrix ...

  2. spring.profiles.active配置了没生效_微服务架构之「 配置中心 」

    在微服务架构的系列文章中,前面已经通过文章<微服务架构之「服务网关 」>介绍过了在微服务中服务网关的原理和应用,今天这篇文章我们继续来聊一聊微服务中另外一个重要模块:「 配置中心 」.后面 ...

  3. spring.profiles.active配置了没生效_一文带你彻底学会 Git Hooks 配置

    你好,我是小桔,是一个没有感情的代码崽. 今天给大家介绍一下 Git Hooks,相信 Git 大家都在用吧,Git 除了用作版本控制,还有许多高级功能,Git Hooks 就是其中之一. 本文环境: ...

  4. .net core 装了没生效_王者荣耀:辅助装出现惊天bug?辅助光环对自己无效?

    大家好,我是老刘备.今天说的这个bug我已经发现许久,从新版本以来就一直在出现,起初我以为是辅助装的光环改动了,但是最近和我的小伙伴开黑之后也遇到这个bug,才发现不是如此. 本期我就来带大家一起看看 ...

  5. lay-verify=required 没生效_眼睛一闭一睁,20万没了!|侧翻|交通事故|半挂车|追尾...

    (原标题:眼睛一闭一睁,20万没了!) 第五届"创赢台州"(电商直播)创业大赛当前正在火热报名中,市政府举办,规模高.奖励多,总奖金16万,一等奖5万,还可获得本人(团队)销售并已 ...

  6. 单行溢出隐藏没生效_至今没搞懂,为什么这个缸这么火?

    [首先] 用主石-火山岩来做个隐藏的过滤 看看这块火山岩的各个角度 火山石隐藏过滤制作开始 第一步50mm钻头开孔 (好像听到了耳膜挣扎的呐喊) 40mm钻头再次掘进 30mm钻头再次掘进 用12mm ...

  7. python中pygame背景颜色为啥没生效_如何更改pygame中的背景图像?

    首先,这里是带有固定缩进的相关代码其次,我假设gameDisplay = pygame.display.set_mode((800, 600)).在def bathRoom(): bathroom = ...

  8. 单行溢出隐藏没生效_溢出隐藏:最全的利用css解决内容溢出问题的几种方案

    在p布局中,有的文字内容多了会超过溢出我们限制的高度,有的图片会撑破DIV,让网页错位变乱.内容溢出了容器,超出了容器所限定的宽度和高度应该怎么办呢?可以将文本溢出部分进行隐藏或者用省略号代替,那具体 ...

  9. 单行溢出隐藏没生效_小Tip:关于单行/多行文本溢出隐藏的一些看法

    最早的文本溢出隐藏只是简单的hidden,把看不见的都给"去掉",就像这样: 哈哈哈哈哈哈哈哈哈哈哈 .hid{ width: 100px; height: 20px; overf ...

  10. 读取扫码枪输入_为何超市“扫码枪”这么强?不输密码钱就没了,现在知道还不晚...

     点上面蓝色字免费关注! 随着互联网的产生,我们的生活也发生了很大的变化,不仅变得更加便利,生活也变得丰富多彩一些,而有了网络之后,移动支付也应运而生,我们的支付方式也发生了很大的改变. 如今只要携带 ...

最新文章

  1. 图解八大排序算法——我见过的最详细的讲解(转)
  2. html浏览器影响js问题,js 浏览器兼容性问题
  3. js jQuery取消添加超链接的方法小结
  4. LINUx打包命令汇总
  5. 白盒测试方法静态分析_静态分析的教育方面
  6. 主要版本发布后Java开发人员应使用的15种工具
  7. 基于SGIP协议编写短信网关接口
  8. C++ Vectors
  9. jQuery实现左移右移
  10. python aes new_python AES 加密
  11. RuntimeError: Exporting the operator prim_DictConstruct to ONNX opset version 11 is not supported.
  12. Unity Container 应用示例
  13. WinForm界面开发
  14. 图森未来高层动荡:CEO侯晓迪被突然免职 公开喊冤
  15. coq程序编写好用的IDE推荐
  16. Rancher+k3s+阿里云流水线详细配置教程
  17. MacBook 快捷键个人总结和设置
  18. 鸿蒙系统桌面加插件,华为鸿蒙OS 2系统最常用UI桌面模块化体验
  19. gvfsd-trash占用内存高时,清空回收站
  20. NOIP模拟测试19

热门文章

  1. 【肌电信号】基于matlab GUI肌电信号处理【含Matlab源码 966期】
  2. 【语音合成】基于matlab语音信号变调【含Matlab源码 566期】
  3. 【图像边缘检测】基于matlab最小二乘法椭圆边缘检测【含Matlab源码146期】
  4. ai人工智能_相信AI?
  5. ai生成图片是什么技术_什么是生成型AI?
  6. docker 指定网卡_Docker数据卷备份恢复、桥接网络设置
  7. 获取两个数组的差 php,php-获取2个数组之间的差
  8. OracleLinux6的安装
  9. APP加密,让你的移动应用更安全!
  10. 一键安装Tengine服务器,TengineRPM(LTMP)构建高效、稳定、安全、易用的Web平台