自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Dubbo 配置 Loadbalance 不生效?擼一把源碼

開發(fā) 前端
很久之前我給業(yè)務(wù)方寫了一個 dubbo loadbalance 的擴(kuò)展(為了敘述方便,這個 loadbalance 擴(kuò)展就叫它 XLB 吧),這兩天業(yè)務(wù)方反饋說 XLB 不生效了。

[[432923]]

文末本文轉(zhuǎn)載自微信公眾號「捉蟲大師」,作者捉蟲大師 。轉(zhuǎn)載本文請聯(lián)系捉蟲大師公眾號。

背景

很久之前我給業(yè)務(wù)方寫了一個 dubbo loadbalance 的擴(kuò)展(為了敘述方便,這個 loadbalance 擴(kuò)展就叫它 XLB 吧),這兩天業(yè)務(wù)方反饋說 XLB 不生效了

我心想,不可能啊,都用了大半年了~

排查

于是我登上不生效的 consumer 機(jī)器進(jìn)行排查,還好我留了一手,當(dāng) XLB 加載時,會打印一行日志

看了下這個服務(wù),并沒有打印日志,說明 XLB 并沒有加載成功

于是,我就去問對應(yīng)的開發(fā),有按照我的文檔配置 loadbalance 嗎?答復(fù):完全按照文檔配置

這下我就有點不相信了,但轉(zhuǎn)念一想,配置 loadbalance 如此簡單,不應(yīng)該出錯啊,我的文檔和他的應(yīng)用都在 xml 文件中配置了 consumer 的 loadbalance

  1. <dubbo:consumer loadbalance="xlb"/> 

抱著試一試的態(tài)度,拉取了他們項目的代碼,發(fā)現(xiàn)配置確實如上,但我發(fā)現(xiàn)他們的 application.properties 配置文件也配了一個 consumer 的屬性

  1. dubbo.consumer.check=false 

以多年和 dubbo 打交道的經(jīng)驗來說,這里有問題,又確認(rèn)了代碼,確實 xml 和 application.properties 都加載了

那這里可能就有問題了,dubbo 從 xml 加載生成了一個 consumer 配置,dubbo-springboot-starter 又從 application.properties 加載配置生成了一個 consumer 配置,這不就沖突了?

別看只配置了 dubbo.consumer.check,它實際上會生成一個完整的 consumer 配置,只不過 loadbalance 為默認(rèn)值

業(yè)務(wù)方為什么會這樣配置?大概率是因為我的文檔里只給出了 xml 形式的配置,沒有給 spring-boot 配置,他們原先使用的是 spring-boot 的配置方式,然后看到我的文檔是 xml,結(jié)果就不會配置了,也寫了個 xml,和原先的配置沖突

驗證

為了驗證是這個問題導(dǎo)致,我把他的 application.properties 的 dubbo.consumer.check 配置挪到了 xml 文件中,果然重啟后就加載到了 XLB

隨后我又在本地的測試應(yīng)用上做了這樣一個驗證:

  1. <!-- case 1 --> 
  2. <dubbo:consumer /> 
  3. <dubbo:consumer loadbalance="xlb"/> 
  4.  
  5. <!-- case 2 --> 
  6. <dubbo:consumer loadbalance="xlb"/> 
  7. <dubbo:consumer /> 

兩組配置相同,但順序不同,測試結(jié)果為 case 1 可以加載到 XLB,case 2 不行

于是猜測,dubbo consumer 配置以后加載的為準(zhǔn)

擼源碼

顯然猜測不符合我的風(fēng)格,下面開擼源碼,不感興趣可以劃過,最下面有總結(jié)

首先搞清楚,何時會加載 loadbalance,在 AbstractClusterInvoker 的 invoke 方法中,加載了 loadbalance

  1. @Override 
  2. public Result invoke(final Invocation invocation) throws RpcException { 
  3.     ... 
  4.     List<Invoker<T>> invokers = list(invocation); 
  5.     LoadBalance loadbalance = initLoadBalance(invokers, invocation); 
  6.     RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation); 
  7.     return doInvoke(invocation, invokers, loadbalance); 

加載代碼如下

  1. protected LoadBalance initLoadBalance(List<Invoker<T>> invokers, Invocation invocation) { 
  2.     if (CollectionUtils.isNotEmpty(invokers)) { 
  3.         return ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(invokers.get(0).getUrl() 
  4.                 .getMethodParameter(RpcUtils.getMethodName(invocation), LOADBALANCE_KEY, DEFAULT_LOADBALANCE)); 
  5.     } else { 
  6.         return ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(DEFAULT_LOADBALANCE); 
  7.     } 

帶緩存的加載擴(kuò)展

  1. public T getExtension(String name) { 
  2.     if (StringUtils.isEmpty(name)) { 
  3.         throw new IllegalArgumentException("Extension name == null"); 
  4.     } 
  5.     if ("true".equals(name)) { 
  6.         return getDefaultExtension(); 
  7.     } 
  8.     final Holder<Object> holder = getOrCreateHolder(name); 
  9.     Object instance = holder.get(); 
  10.     if (instance == null) { 
  11.         synchronized (holder) { 
  12.             instance = holder.get(); 
  13.             if (instance == null) { 
  14.                 instance = createExtension(name); 
  15.                 holder.set(instance); 
  16.             } 
  17.         } 
  18.     } 
  19.     return (T) instance; 

可以看出

  • loadbalance 是發(fā)起 dubbo 調(diào)用時,且當(dāng) invokers 非空時(即 providers 非空)會被初始化,后續(xù)都從緩存中取
  • loadbalance 是根據(jù)第一個 invoker 的 loadbalance 參數(shù)決定使用哪個 loadbalance 的

于是問題轉(zhuǎn)移到 invoker 的 loadbalance 從哪來?provider 不會配置 loadbalance,所以這個參數(shù)一定是從 consumer 的配置上得到的

順藤摸瓜,在 RegistryDirectory 的 toInvokers 方法中調(diào)用了 mergeUrl,它是在注冊中心通知時被調(diào)用,也就是從注冊中心上拿到 provider url 時,還得 merge 一下才能用,merge 了些什么內(nèi)容?

  1. private URL mergeUrl(URL providerUrl) { 
  2.     // 1. merge consumer 參數(shù) 
  3.     providerUrl = ClusterUtils.mergeUrl(providerUrl, queryMap);  
  4.     // 2. merge configurator 參數(shù) 
  5.     providerUrl = overrideWithConfigurator(providerUrl); 
  6.     ... 
  7.     return providerUrl; 

1中 merge 了queryMap 里的參數(shù),這個queryMap 其實就是 consumer 的參數(shù),它來自配置的 reference

再看 reference 配置,當(dāng) ReferenceConfig 初始化時

  1. public synchronized void init() { 
  2.     ... 
  3.     checkAndUpdateSubConfigs(); 
  4.     ... 
  5.     AbstractConfig.appendParameters(map, consumer); 
  6.     ... 
  7.  
  8. // 2 
  9. public void checkAndUpdateSubConfigs() { 
  10.     ... 
  11.     checkDefault(); 
  12.     ... 
  13.  
  14. // 3 
  15. public void checkDefault() throws IllegalStateException { 
  16.     if (consumer == null) { 
  17.         consumer = ApplicationModel.getConfigManager() 
  18.                 .getDefaultConsumer() 
  19.                 .orElse(new ConsumerConfig()); 
  20.     } 
  21.  
  22. // 4 
  23. public Optional<ConsumerConfig> getDefaultConsumer() { 
  24.     List<ConsumerConfig> consumerConfigs = getDefaultConfigs(getConfigsMap(getTagName(ConsumerConfig.class))); 
  25.     if (CollectionUtils.isNotEmpty(consumerConfigs)) { 
  26.         return Optional.of(consumerConfigs.get(0)); 
  27.     } 
  28.     return Optional.empty(); 

上面調(diào)用鏈從 1 到 4,4 中獲取了第1個 consumer,這就是我們要找的根源

總結(jié)

每配置一個 consumer ,無論是從 xml 文件,或是 spring-boot 配置,或是 api 直接創(chuàng)建,都會生成一個 consumerConfig 對象

當(dāng)消費接口,即配置 reference 時,會將 consumer 的參數(shù) merge 過來,如果存在多個 consumer,會挑第一個,當(dāng)然我們并不知道誰先加載

當(dāng) reference 存在 consumer 的配置時,注冊中心通知的 provider urls 會和 reference 的參數(shù)進(jìn)行合并,合并后生成可調(diào)用的 invoker

 

 

 

對于 loadbalance 來說,調(diào)用時,如果 invokers 非空,則會嘗試通過第一個 invoker 的 loadbalance 參數(shù)加載負(fù)載均衡算法,第一次調(diào)用進(jìn)行加載,后續(xù)調(diào)用則使用緩存

 

責(zé)任編輯:武曉燕 來源: 捉蟲大師
相關(guān)推薦

2020-03-02 17:04:47

戴爾

2023-06-21 08:24:46

2011-05-04 17:11:12

打印機(jī)

2011-11-08 08:14:40

WLANWi-Fi

2024-01-04 14:16:05

騰訊紅黑樹Socket

2022-10-25 15:25:22

網(wǎng)關(guān)并行Flowable

2010-10-28 08:43:07

App StoreSymbian

2017-06-14 17:39:40

微服務(wù)架構(gòu)服務(wù)器

2019-06-12 15:20:25

Redis高性能線程

2024-02-22 17:08:03

騰訊架構(gòu)RocketMQ

2009-02-23 19:07:14

SaaS800APP八百客

2021-08-18 23:10:56

setState代碼性能

2018-03-23 08:26:44

Hadoop集群SQL

2024-04-18 08:00:23

openInula?React響應(yīng)式 API

2022-07-20 08:55:02

區(qū)塊鏈技術(shù)數(shù)據(jù)記錄

2011-04-08 15:28:48

2011-04-08 15:15:34

策略路由

2014-11-26 15:05:16

魅族MX4Pro

2021-06-03 08:01:12

JVM性能優(yōu)化

2019-10-30 05:51:07

物聯(lián)網(wǎng)設(shè)備物聯(lián)網(wǎng)安全物聯(lián)網(wǎng)
點贊
收藏

51CTO技術(shù)棧公眾號