同時(shí)使用@LoadBalanced?@RefreshScope注解負(fù)載均衡失效分析
背景
最近引入了 Nacos Config 配置管理能力,說(shuō)起來(lái)用法很簡(jiǎn)單,還是踩了三個(gè)坑。
- Nacos Config 的 nacos 的帳號(hào)密碼加密配置后,怎么解密而且在
NacosConfigBootstrapConfiguration真正注入 Nacos Config 注入之前,而且不能觸發(fā)NacosDiscoveryProperties的isNacosDiscoveryInfoChanged變動(dòng)事件。因?yàn)?NacosDiscoveryProperties接受NacosContextRefresher事件時(shí),還是從 yml 配置中獲取屬性,不會(huì)從Environment對(duì)象中加載。 @RefreshScope要想生效,該注意什么?非 shared-config 的配置變動(dòng)時(shí),要想實(shí)時(shí)生效,必須在當(dāng)前應(yīng)用的 bootstrap.yml 中配置spring.application.name屬性,注冊(cè)該應(yīng)用在配置中心需要監(jiān)聽(tīng)的配置。@RefreshScope + @LoadBalanced同時(shí)使用導(dǎo)致 Ribbon 負(fù)載均衡失效問(wèn)題。
問(wèn)題一比較復(fù)雜,此處不做討論,本文記錄問(wèn)題三的解決方法及個(gè)人思考。
問(wèn)題
有個(gè)模塊使用了 @LoadBalanced 負(fù)載均衡,通過(guò)配置控制超時(shí)時(shí)間。
引入 Nacos Config 配置后,按照常規(guī)用法,在對(duì)象上添加了 @RefreshScope 屬性,希望配置變動(dòng)時(shí),能實(shí)時(shí)生效。
注入代碼如下:
@Value("${rest.template.connect-timeout:10000}")
private Integer connectTimeout;
@Value("${rest.template.read-timeout:10000}")
private Integer readTimeout;
@Bean
@RefreshScope
@LoadBalanced
public RestTemplate restTemplate(RestTemplateBuilder builder){
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(connectTimeout); //連接超時(shí)設(shè)置
requestFactory.setReadTimeout(readTimeout); //讀寫超時(shí)設(shè)置
RestTemplate restTemplate = new RestTemplate(requestFactory);
logger.info("初始化負(fù)載均衡的 RestTemplate 對(duì)象 {} {}", connectTimeout, readTimeout);
return restTemplate;
}
修改配置中心的配置后,可以監(jiān)控到 RestTemplate 會(huì)在配置變化后重新初始化了,也打印了最新的配置。

但真正使用這個(gè)類,調(diào)用某個(gè)服務(wù)時(shí),出現(xiàn)了服務(wù)無(wú)法解析的異常:

分析
首先,檢查調(diào)用的目標(biāo)服務(wù)是否注冊(cè)成功,目標(biāo)服務(wù)是正常啟動(dòng)的。
其次,對(duì)比其他同樣引用了 @LoadBalanced 的 RestTemplate 的模塊,它調(diào)用是正常的。
最后,對(duì)比異常調(diào)用和正常調(diào)用的注入代碼的區(qū)別,多了一個(gè) @RefreshScope ,調(diào)整代碼驗(yàn)證結(jié)果正常。引入 @RefreshScope 時(shí),在配置變化后才會(huì)發(fā)生這個(gè)異常,首次運(yùn)行時(shí)正常的。
延伸搜索發(fā)現(xiàn),負(fù)載均衡 RestTemplate 也有類似的問(wèn)題 @scope("prototype")+@loadbalanced注解時(shí)負(fù)載均衡失效問(wèn)題。
啟示錄
@LoadBalanced 和 @RefreshScope 同時(shí)使用,首次初始化時(shí),RestTemplate 對(duì)象具有負(fù)載均衡的能力;當(dāng) Nacos 配置中的配置變動(dòng)時(shí),這個(gè)對(duì)象會(huì)重新創(chuàng)建,而且此時(shí)并沒(méi)有使用 @LoadBalanced 的能力,導(dǎo)致負(fù)載均衡失效。
就是說(shuō),這兩個(gè)注解同時(shí)使用時(shí),在不同的時(shí)機(jī),只會(huì)有一個(gè)注解生效:
- 初始創(chuàng)建時(shí),
@LoadBalanced生效,系統(tǒng)中的實(shí)例是負(fù)載均衡的RestTemplate; - 當(dāng) Nacos 配置變化,
NacosContextRefresher觸發(fā)通知@RefreshScope注解的@Bean對(duì)象時(shí),重新創(chuàng)建的實(shí)例就是普通的RestTemplate了。
引入任何一個(gè)第三方工具,面對(duì)的都是黑盒,各種資料用法看似簡(jiǎn)單,一用就坑不斷??!建議 Nacos Config 官方配置給出一個(gè)使用建議 @RefreshScope 不要用在 @LoadBalanced 注解上。
最后記錄一個(gè)偶然的發(fā)現(xiàn):

選中幾個(gè)圖片文件后,右側(cè)概覽圖是一個(gè)堆疊的圖,才注意到!
以上就是同時(shí)使用@LoadBalanced @RefreshScope負(fù)載均衡失效分析的詳細(xì)內(nèi)容,更多關(guān)于@LoadBalanced @RefreshScope失效的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Spring動(dòng)態(tài)加載bean后調(diào)用實(shí)現(xiàn)方法解析
這篇文章主要介紹了Spring動(dòng)態(tài)加載bean后調(diào)用實(shí)現(xiàn)方法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08
SpringBoot學(xué)習(xí)之Json數(shù)據(jù)交互的方法
這篇文章主要介紹了SpringBoot學(xué)習(xí)之Json數(shù)據(jù)交互的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-12-12
Java List簡(jiǎn)介_(kāi)動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
Java中可變數(shù)組的原理就是不斷的創(chuàng)建新的數(shù)組,將原數(shù)組加到新的數(shù)組中,下文對(duì)Java List用法做了詳解。需要的朋友參考下吧2017-05-05
java后端請(qǐng)求過(guò)濾options方式
一文詳解SpringBoot?Redis多數(shù)據(jù)源配置
Java十大經(jīng)典排序算法的實(shí)現(xiàn)圖解

