成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

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

[[432923]]

文末本文轉載自微信公眾號「捉蟲大師」,作者捉蟲大師 。轉載本文請聯系捉蟲大師公眾號。

背景

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

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

排查

于是我登上不生效的 consumer 機器進行排查,還好我留了一手,當 XLB 加載時,會打印一行日志

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

于是,我就去問對應的開發,有按照我的文檔配置 loadbalance 嗎?答復:完全按照文檔配置

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

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

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

  1. dubbo.consumer.check=false 

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

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

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

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

驗證

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

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

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

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

于是猜測,dubbo consumer 配置以后加載的為準

擼源碼

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

首先搞清楚,何時會加載 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.     } 

帶緩存的加載擴展

  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 是發起 dubbo 調用時,且當 invokers 非空時(即 providers 非空)會被初始化,后續都從緩存中取
  • loadbalance 是根據第一個 invoker 的 loadbalance 參數決定使用哪個 loadbalance 的

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

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

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

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

再看 reference 配置,當 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(); 

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

總結

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

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

當 reference 存在 consumer 的配置時,注冊中心通知的 provider urls 會和 reference 的參數進行合并,合并后生成可調用的 invoker

 

 

 

對于 loadbalance 來說,調用時,如果 invokers 非空,則會嘗試通過第一個 invoker 的 loadbalance 參數加載負載均衡算法,第一次調用進行加載,后續調用則使用緩存

 

責任編輯:武曉燕 來源: 捉蟲大師
相關推薦

2020-03-02 17:04:47

戴爾

2023-06-21 08:24:46

2011-05-04 17:11:12

打印機

2024-01-04 14:16:05

騰訊紅黑樹Socket

2011-11-08 08:14:40

WLANWi-Fi

2010-10-28 08:43:07

App StoreSymbian

2019-06-12 15:20:25

Redis高性能線程

2024-02-22 17:08:03

騰訊架構RocketMQ

2017-06-14 17:39:40

微服務架構服務器

2022-10-25 15:25:22

網關并行Flowable

2009-02-23 19:07:14

SaaS800APP八百客

2018-03-23 08:26:44

Hadoop集群SQL

2021-08-18 23:10:56

setState代碼性能

2024-04-18 08:00:23

openInula?React響應式 API

2022-07-20 08:55:02

區塊鏈技術數據記錄

2019-10-30 05:51:07

物聯網設備物聯網安全物聯網

2021-06-03 08:01:12

JVM性能優化

2014-11-26 15:05:16

魅族MX4Pro

2020-11-12 07:51:05

DockerSpring Boot應用

2020-03-27 11:41:12

線程 Java中止
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲欧美在线一区 | 国产毛片av | 亚洲视频在线一区 | 青青草华人在线视频 | 天天草天天爱 | 欧美日韩精品亚洲 | 精品av | 色频| 99福利视频 | 在线免费毛片 | 国产乱码精品一区二区三区中文 | 成人福利 | 狠狠爱一区二区三区 | 国产乱码精品一区二区三区五月婷 | 国产亚洲欧美在线 | 欧美中文在线 | 日韩三级电影一区二区 | 国产精品视频播放 | 中文字幕丁香5月 | 国产精品夜夜春夜夜爽久久电影 | 国产成人精品久久二区二区91 | 中文区中文字幕免费看 | 欧美性影院 | 污污的网站在线观看 | 欧美区日韩区 | 伊人一区| 国产精品96久久久久久 | 国产精品69毛片高清亚洲 | 天天玩天天干天天操 | 精品国产乱码久久久久久闺蜜 | 视频一区在线 | 成人伊人 | 视频三区 | 亚洲午夜网 | 亚洲不卡在线观看 | 狠狠做深爱婷婷综合一区 | 荷兰欧美一级毛片 | 99这里只有精品视频 | 久久久妇女国产精品影视 | 欧美视频在线观看 | 99精品国产一区二区三区 |