hystrix配置中Apollo與Archaius對(duì)比分析
前言
feign是一個(gè)出色的Http請(qǐng)求客戶端封裝框架,feign-hystrix是整個(gè)框架體系里的其中一個(gè)模塊,用來集成hystrix熔斷器的,feign和hystrix這兩個(gè)項(xiàng)目都是Netflix開源的(openfeign已獨(dú)立迭代)。在spring boot項(xiàng)目中,可以使用spring-cloud-starter-openfeign模塊,無縫集成feign和hystrix。但是,hystrix默認(rèn)采用的Archaius來驅(qū)動(dòng)hystrix的配置系統(tǒng),無縫集成的同時(shí),也會(huì)把a(bǔ)rchaius-core給引入進(jìn)來。archaius是一個(gè)配置中心項(xiàng)目,類似spring cloud config和apollo,如果archaius只是作為hystrix配置的驅(qū)動(dòng),項(xiàng)目啟動(dòng)時(shí)會(huì)打印煩人的警告日志,提示你沒有配置任何動(dòng)態(tài)配置源。當(dāng)項(xiàng)目里已經(jīng)采用了apollo時(shí),可以直接剔除掉Archaius,他們的功能定位高度重合了。直接剔除依賴,會(huì)導(dǎo)致原本配置在spring中的配置不生效,博主也是在不小心剔除后,遇到了配置不生效的問題,才有了本篇博文,記錄下過程。只要稍加改動(dòng),結(jié)合apollo配置動(dòng)態(tài)下發(fā)能力,可以做到hystrix的配置實(shí)時(shí)動(dòng)態(tài)生效。
- 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.
我們遇到的問題
在一次系統(tǒng)優(yōu)化重構(gòu)中,博主給整個(gè)項(xiàng)目來了一個(gè)360的大瘦身,把所有的未使用的依賴統(tǒng)統(tǒng)給挪走了。其中就包括了spring-cloud-starter-openfeign模塊的archaius-core依賴。因?yàn)槲覀円呀?jīng)使用了apollo配置中心,archaius在這個(gè)項(xiàng)目里顯得很多余,而且還會(huì)打印煩人的警告日志。所以就直接排除了,如:
implementation ('org.springframework.cloud:spring-cloud-starter-openfeign'){
exclude(module:"archaius-core")
}為此,專門了解了下archaius的來歷,并且針對(duì)feign的熔斷器的Fallback能力進(jìn)行了測(cè)試,一切運(yùn)行正常。上線一周后,問題暴露出來了,同事反饋,hystrix的配置好像不生效了?,F(xiàn)象是,原本設(shè)置的hystrix線程執(zhí)行不超時(shí),卻發(fā)生了很多執(zhí)行一秒就超時(shí)了,我們的關(guān)鍵配置如下(這不是一個(gè)很好的配置示范,后面會(huì)調(diào)整更細(xì)粒度控制):
#禁止執(zhí)行超時(shí) hystrix.command.default.execution.timeout.enabled = false
直觀感覺就是這個(gè)配置不生效了,聯(lián)想到archaius-core被移除,所以先立馬恢復(fù)了依賴,重新打包上線,問題解決。就這?為了徹底搞清楚Hystrix的配置加載過程,我們對(duì)feign整合hystrix進(jìn)行了全面的了解。
HYSTRIX在FEIGN中的加載過程
在spring-cloud-starter-openfeign的封裝下,使用起來非常簡(jiǎn)單,但是內(nèi)部的加載流程非常復(fù)雜。所以博主也不打算全面鋪開來說這塊內(nèi)容,有機(jī)會(huì)會(huì)獨(dú)立一篇來說。這里根據(jù)我們上文遇到的禁用執(zhí)行超時(shí)不生效的問題,博主總結(jié)了加載流程中的幾個(gè)關(guān)鍵的地方:
Feign和Hystrix的橋接器Feign-Hystrix

這個(gè)項(xiàng)目是feign和hystrix的橋接器,通過這樣的一個(gè)橋接器,將兩個(gè)框架的api能力整合在了一起,下面簡(jiǎn)要闡述下,加載過程關(guān)鍵類的作用:
SetterFactory:承載了構(gòu)造HystrixCommand實(shí)例的所有的配置的接口,有一個(gè)默認(rèn)實(shí)現(xiàn)Default,在下面會(huì)用到,是自定義配置實(shí)現(xiàn)的突破口
HystrixInvocationHandler:這是一個(gè)實(shí)現(xiàn)了JDK代理接口類,用來代理Feign最終的執(zhí)行,HystrixCommand類就是在這個(gè)實(shí)例里被構(gòu)造執(zhí)行的,使用的構(gòu)造方法正是帶入?yún)etter的構(gòu)造方法,集成方會(huì)實(shí)現(xiàn)SetterFactory來構(gòu)造Setter。調(diào)試程序時(shí)我們將端點(diǎn)打進(jìn)這個(gè)類里,就可以看到配置加載的情況

SPRING BOOT自動(dòng)加載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框架下加載的總?cè)肟?。這個(gè)默認(rèn)的構(gòu)建器Builder中,有一個(gè)默認(rèn)實(shí)現(xiàn)的SetterFactory,這個(gè)SetterFactory專門負(fù)責(zé)傳遞參數(shù)給Hystrix初始化HystrixCommand用??梢钥吹竭@里Bean的實(shí)例化加上了@ConditionalOnMissingBean條件約束,既我們可以自定義實(shí)現(xiàn)Hystrix的構(gòu)造器,覆蓋這里的實(shí)現(xiàn),在自定義的構(gòu)造器中,可以通過自定義實(shí)現(xiàn)SetterFactory,來注入任意的配置。這個(gè)是實(shí)現(xiàn)Hystrix配置自定義加載的方式之一,不過不推薦,沒必要破壞spirng現(xiàn)有的這種結(jié)構(gòu),而且代碼也會(huì)比較冗長(下面{...}省略了一百多行配置處理代碼,用來兼容Hystrix現(xiàn)有配置定義),看起來如下:

HYSTRIX的動(dòng)態(tài)兜底配置
配置是hystrix的核心,各種策略的選擇執(zhí)行都需要配置來驅(qū)動(dòng),所以,雖然在應(yīng)用層面不需要太多的配置設(shè)置,但是必要的配置hystrix都會(huì)填充一個(gè)默認(rèn)值,比如,hystrix默認(rèn)執(zhí)行超時(shí)設(shè)置的1s。Hystrix中的配置有三個(gè)層次的加載優(yōu)先級(jí),如:
- 最先加載Setter:Setter是用戶傳遞給Hystrix構(gòu)造器的,所以優(yōu)先級(jí)別最高
- 其次加載動(dòng)態(tài)配置源:如果必要的配置在Setter里沒有找到,則在動(dòng)態(tài)配置源中獲取
- 最后加載默認(rèn)配置:如果動(dòng)態(tài)配置源中也沒有找到配置,則采用默認(rèn)的配置
其中動(dòng)態(tài)配置源,有一個(gè)基于SystemProperties的配置實(shí)現(xiàn)HystrixDynamicPropertiesSystemProperties。HystrixCommand在實(shí)例化時(shí),如果用戶沒有給到具體的配置,Hystrix每次都會(huì)去SystemProperties中尋找配置。也就是說,我們可以通過-D參數(shù)注入任意Hystrix的配置參數(shù),都會(huì)生效。有了這個(gè)特性,可以非常簡(jiǎn)單的結(jié)合apollo,達(dá)到hystrix配置動(dòng)態(tài)生效的效果,而且所有配置兼容Hystrix原本的配置。
APOLLO配置驅(qū)動(dòng)HYSTRIX
實(shí)現(xiàn)這個(gè)功能的關(guān)鍵是。系統(tǒng)初始化時(shí),將hystrix.command前綴相關(guān)的配置從apollo中獲取到然后統(tǒng)統(tǒng)注入SystemProperties。配置更新時(shí),同時(shí)更新SystemProperties中的配置即可,非常簡(jiǎn)單,用代碼說話:
/**
* @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(Setconfigkyes) {
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);
}
});
}
}這里注意一個(gè)問題:為啥這里多設(shè)計(jì)了一個(gè)dynamic.前綴的配置,這是因?yàn)椴┲髟跍y(cè)試過程中觸發(fā)了apollo配置監(jiān)聽器隱藏的問題,導(dǎo)致Apollo的動(dòng)態(tài)監(jiān)聽器不生效了。Apollo配置加載是以SystemProperties為最高優(yōu)先級(jí)的,當(dāng)配置發(fā)生變化時(shí),apollo會(huì)將SystemProperties覆蓋到配置之后,才比較本次配置發(fā)布是否有更新。因?yàn)槲覀円婚_始就將相關(guān)的配置加載到SystemProperties里了,所以每次變更都會(huì)被覆蓋成之前的值,導(dǎo)致更新判斷失效,一直進(jìn)不了監(jiān)聽器。如果想要?jiǎng)討B(tài)更新,就需要維護(hù)一份apollo的配置和SystemProperties里的映射關(guān)系,而不能保持一致,這樣每次修改apollo時(shí),就可以將維護(hù)映射關(guān)系的前綴去掉,然后將值動(dòng)態(tài)更新到SystemProperties。目前的設(shè)計(jì)里,既支持原生的所有配置一次性加載,也支持dynamic.前綴拼裝原有配置動(dòng)態(tài)加載
配置示例
#初始化時(shí)一次性加載 hystrix.command.default.execution.timeout.enabled = true #每次修改動(dòng)態(tài)生效 dynamic.hystrix.command.default.execution.timeout.enabled = true
結(jié)語
Feign-hystrix的配置,有了Apollo,還用Archaius嗎?當(dāng)然不用,采用apollo實(shí)現(xiàn)方案,既兼容了所有原生配置,還可以做到動(dòng)態(tài)生效,豈不美哉。
以上就是hystrix配置中Apollo與Archaius對(duì)比分析的詳細(xì)內(nèi)容,更多關(guān)于hystrix配置Apollo與Archaius對(duì)比的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java中關(guān)于轉(zhuǎn)義字符的一個(gè)bug
本文主要介紹了java中關(guān)于轉(zhuǎn)義字符的一個(gè)bug。具有很好的參考價(jià)值,下面跟著小編一起來看下吧2017-02-02
詳解JUC并發(fā)編程中的進(jìn)程與線程學(xué)習(xí)
這篇文章主要為大家詳細(xì)介紹了JUC并發(fā)編程中的進(jìn)程與線程學(xué)習(xí),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-03-03
SpringBoot+jpa配置如何根據(jù)實(shí)體類自動(dòng)創(chuàng)建表
這篇文章主要介紹了SpringBoot+jpa配置如何根據(jù)實(shí)體類自動(dòng)創(chuàng)建表,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
Java高并發(fā)編程之CAS實(shí)現(xiàn)無鎖隊(duì)列代碼實(shí)例
這篇文章主要介紹了Java高并發(fā)編程之CAS實(shí)現(xiàn)無鎖隊(duì)列代碼實(shí)例,在多線程操作中,我們通常會(huì)添加鎖來保證線程的安全,那么這樣勢(shì)必會(huì)影響程序的性能,那么為了解決這一問題,于是就有了在無鎖操作的情況下依然能夠保證線程的安全,需要的朋友可以參考下2023-12-12
Java簡(jiǎn)易抽獎(jiǎng)系統(tǒng)小項(xiàng)目
這篇文章主要為大家詳細(xì)介紹了Java簡(jiǎn)易抽獎(jiǎng)系統(tǒng)小項(xiàng)目,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01
Spring使用注解實(shí)現(xiàn)Bean的自動(dòng)裝配
大家好,本篇文章主要講的是Spring使用注解實(shí)現(xiàn)Bean的自動(dòng)裝配,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下2022-02-02
Spring mvc防止數(shù)據(jù)重復(fù)提交的方法
這篇文章主要為大家詳細(xì)介紹了Spring mvc防止數(shù)據(jù)重復(fù)提交的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11

