日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

dubbo 配置 loadbalance 不生效?撸一把源码

發布時間:2023/12/8 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 dubbo 配置 loadbalance 不生效?撸一把源码 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

背景

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

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

排查

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

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

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

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

<dubbo:consumer loadbalance="xlb"/>

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

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

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

<!-- case 1 --> <dubbo:consumer /> <dubbo:consumer loadbalance="xlb"/><!-- case 2 --> <dubbo:consumer loadbalance="xlb"/> <dubbo:consumer />

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

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

擼源碼

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

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

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

加載代碼如下

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

帶緩存的加載擴展

public T getExtension(String name) {if (StringUtils.isEmpty(name)) {throw new IllegalArgumentException("Extension name == null");}if ("true".equals(name)) {return getDefaultExtension();}final Holder<Object> holder = getOrCreateHolder(name);Object instance = holder.get();if (instance == null) {synchronized (holder) {instance = holder.get();if (instance == null) {instance = createExtension(name);holder.set(instance);}}}return (T) instance; }

可以看出

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

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

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

private URL mergeUrl(URL providerUrl) {// 1. merge consumer 參數providerUrl = ClusterUtils.mergeUrl(providerUrl, queryMap); // 2. merge configurator 參數providerUrl = overrideWithConfigurator(providerUrl);...return providerUrl; }

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

再看 reference 配置,當 ReferenceConfig 初始化時

// 1 public synchronized void init() {...checkAndUpdateSubConfigs();...AbstractConfig.appendParameters(map, consumer);... }// 2 public void checkAndUpdateSubConfigs() {...checkDefault();... }// 3 public void checkDefault() throws IllegalStateException {if (consumer == null) {consumer = ApplicationModel.getConfigManager().getDefaultConsumer().orElse(new ConsumerConfig());} }// 4 public Optional<ConsumerConfig> getDefaultConsumer() {List<ConsumerConfig> consumerConfigs = getDefaultConfigs(getConfigsMap(getTagName(ConsumerConfig.class)));if (CollectionUtils.isNotEmpty(consumerConfigs)) {return Optional.of(consumerConfigs.get(0));}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 參數加載負載均衡算法,第一次調用進行加載,后續調用則使用緩存

搜索關注微信公眾號"捉蟲大師",后端技術分享,架構設計、性能優化、源碼閱讀、問題排查、踩坑實踐。

總結

以上是生活随笔為你收集整理的dubbo 配置 loadbalance 不生效?撸一把源码的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 波多野结衣www | 激情婷婷六月 | 潘金莲三级80分钟 | 噜噜噜久久久 | 成人91在线观看 | 中文字幕无线码一区 | 日韩欧美在线视频观看 | 免费国产a级片 | 91蜜桃视频在线观看 | 亚洲av成人无码一二三在线观看 | 亚洲精品在线看 | 91视频在线 | 亚洲国产精品一区二区尤物区 | 中文字幕日韩一区二区三区 | 精品一区李梓熙捆绑 | 最近最新最好看的2019 | 久久这里只有精品23 | 东京av男人的天堂 | 成人av影视在线 | 日韩网站免费观看高清 | 欧美日韩一区三区 | 欧美国产中文 | 午夜天堂精品久久久久 | 日本在线视频播放 | 亚洲免费精品视频 | 波多野结衣一区在线 | 欧美裸体网站 | 欧美日韩卡一卡二 | wwwxx日本| 久久精品视频在线观看 | 成人第一页 | xxx视频在线观看 | 久久久久无码国产精品不卡 | 精品人妻少妇嫩草av无码 | 超碰97人人爱 | 中文免费视频 | 亚洲第十页| 国产美女福利 | 精品美女在线观看 | 亚洲理论在线观看 | 国产香蕉在线观看 | www夜夜| 91毛片网| 日韩av一区在线 | 亚洲青青草原 | 污污网站免费在线观看 | 黄色在线不卡 | 欧美极品在线视频 | 无码精品国产一区二区三区 | 欧亚成人av | 亚洲三级黄色 | 看成人片 | 美女的隐私免费看 | 欧美一级在线视频 | 91久久综合| 特级黄色大片 | 精品一级少妇久久久久久久 | 欧美激情伊人 | 香蕉视频网站在线 | 亚洲一区二区三区激情 | 免费久久一级欧美特大黄 | 成人免费91 | 国产男女猛烈无遮挡免费观看网站 | 好男人在线视频 | 国产精品13p| 婷婷综合在线视频 | 欧美图片自拍偷拍 | 国产精品99久久久久久一二区 | 特黄特色大片免费 | 欧美国产二区 | 天天碰天天干 | 深爱激情丁香 | 国产白浆在线 | www.五月激情 | 欧美在线播放一区二区 | www.香蕉网 | 玖玖精品视频 | 午夜伦理视频 | 伊人超碰在线 | 青青草精品在线视频 | 国产粉嫩一区二区三区 | 在线观看第一页 | 七月丁香婷婷 | 欧美黄色大片在线观看 | 中文字幕乱码一区二区 | 夜夜摸夜夜操 | 国产白丝av | 欧美男女性生活视频 | 欧美xxxxx视频| 99精品国产99久久久久久97 | 亚洲免费福利视频 | 青青操狠狠干 | 最近中文字幕在线免费观看 | 一级特黄aa大片免费播放 | 女人毛片视频 | 日韩成人精品在线观看 | 国产福利免费 | 成人教育av在线 | 国产黄色片视频 |