www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當前位置:首頁 > 公眾號精選 > 架構師社區(qū)
[導讀]公眾號「程序員內點事」?對于Nacos大家應該都不太陌生,出身阿里名聲在外,能做動態(tài)服務發(fā)現、配置管理,非常好用的一個工具。然而這樣的技術用的人越多面試被問的概率也就越大,如果只停留在使用層面,那面試可能要吃大虧。比如我們今天要討論的話題,Nacos在做配置中心的時候,配置數據的...

本文來源:公眾號「 程序員內點事」?對于Nacos大家應該都不太陌生,出身阿里名聲在外,能做動態(tài)服務發(fā)現、配置管理,非常好用的一個工具。然而這樣的技術用的人越多面試被問的概率也就越大,如果只停留在使用層面,那面試可能要吃大虧。

比如我們今天要討論的話題,Nacos在做配置中心的時候,配置數據的交互模式是服務端推過來還是客戶端主動拉的?

阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)
這里我先拋出答案:客戶端主動拉的!

接下來咱們扒一扒Nacos源碼,來看看它具體是如何實現的?

配置中心

Nacos之前簡單回顧下配置中心的由來。

簡單理解配置中心的作用就是對配置統(tǒng)一管理,修改配置后應用可以動態(tài)感知,而無需重啟。

因為在傳統(tǒng)項目中,大多都采用靜態(tài)配置的方式,也就是把配置信息都寫在應用內的ymlproperties這類文件中,如果要想修改某個配置,通常要重啟應用才可以生效。

但有些場景下,比如我們想要在應用運行時,通過修改某個配置項,實時的控制某一個功能的開閉,頻繁的重啟應用肯定是不能接受的。

尤其是在微服務架構下,我們的應用服務拆分的粒度很細,少則幾十多則上百個服務,每個服務都會有一些自己特有或通用的配置。假如此時要改變通用配置,難道要我挨個改幾百個服務配置?很顯然這不可能。所以為了解決此類問題配置中心應運而生。

阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)
配置中心

推與拉模型

客戶端與配置中心的數據交互方式其實無非就兩種,要么推push,要么拉pull。

推模型

客戶端與服務端建立TCP長連接,當服務端配置數據有變動,立刻通過建立的長連接將數據推送給客戶端。

優(yōu)勢:長鏈接的優(yōu)點是實時性,一旦數據變動,立即推送變更數據給客戶端,而且對于客戶端而言,這種方式更為簡單,只建立連接接收數據,并不需要關心是否有數據變更這類邏輯的處理。

弊端:長連接可能會因為網絡問題,導致不可用,也就是俗稱的假死。連接狀態(tài)正常,但實際上已無法通信,所以要有的心跳機制KeepAlive來保證連接的可用性,才可以保證配置數據的成功推送。

拉模型

客戶端主動的向服務端發(fā)請求拉配置數據,常見的方式就是輪詢,比如每3s向服務端請求一次配置數據。

輪詢的優(yōu)點是實現比較簡單。但弊端也顯而易見,輪詢無法保證數據的實時性,什么時候請求?間隔多長時間請求一次?都是不得不考慮的問題,而且輪詢方式對服務端還會產生不小的壓力。

長輪詢

開篇我們就給出了答案,nacos采用的是客戶端主動拉pull模型,應用長輪詢(Long Polling)的方式來獲取配置數據。

額?以前只聽過輪詢,長輪詢又是什么鬼?它和傳統(tǒng)意義上的輪詢(暫且叫短輪詢吧,方便比較)有什么不同呢?

短輪詢

不管服務端配置數據是否有變化,不停的發(fā)起請求獲取配置,比如支付場景中前段JS輪詢訂單支付狀態(tài)。

這樣的壞處顯而易見,由于配置數據并不會頻繁變更,若是一直發(fā)請求,勢必會對服務端造成很大壓力。還會造成推送數據的延遲,比如:每10s請求一次配置,如果在第11s時配置更新了,那么推送將會延遲9s,等待下一次請求。

阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)
為了解決短輪詢的問題,有了長輪詢方案。

長輪詢

長輪詢可不是什么新技術,它不過是由服務端控制響應客戶端請求的返回時間,來減少客戶端無效請求的一種優(yōu)化手段,其實對于客戶端來說與短輪詢的使用并沒有本質上的區(qū)別。

客戶端發(fā)起請求后,服務端不會立即返回請求結果,而是將請求掛起等待一段時間,如果此段時間內服務端數據變更,立即響應客戶端請求,若是一直無變化則等到指定的超時時間后響應請求,客戶端重新發(fā)起長鏈接。

阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)

Nacos初識

為了后續(xù)演示操作方便我在本地搭了個Nacos注意:?運行時遇到個小坑,由于Nacos默認是以cluster集群的方式啟動,而本地搭建通常是單機模式standalone,這里需手動改一下啟動腳本startup.X中的啟動模式。

阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)
直接執(zhí)行/bin/startup.X就可以了,默認用戶密碼均是nacos。阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)

幾個概念

Nacos配置中心的幾個核心概念:dataId、groupnamespace,它們的層級關系如下圖:阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)

dataId:是配置中心里最基礎的單元,它是一種key-value結構,key通常是我們的配置文件名稱,比如:application.yml、mybatis.xml,而value是整個文件下的內容。

目前支持JSON、XML、YAML等多種配置格式。阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)

group:dataId配置的分組管理,比如同在dev環(huán)境下開發(fā),但同環(huán)境不同分支需要不同的配置數據,這時就可以用分組隔離,默認分組DEFAULT_GROUP

namespace:項目開發(fā)過程中肯定會有dev、test、pro等多個不同環(huán)境,namespace則是對不同環(huán)境進行隔離,默認所有配置都在public里。

架構設計

下圖簡要描述了nacos配置中心的架構流程。

客戶端、控制臺通過發(fā)送Http請求將配置數據注冊到服務端,服務端持久化數據到Mysql。

客戶端拉取配置數據,并批量設置對dataId的監(jiān)聽發(fā)起長輪詢請求,如服務端配置項變更立即響應請求,如無數據變更則將請求掛起一段時間,直到達到超時時間。為減少對服務端壓力以及保證配置中心可用性,拉取到配置數據客戶端會保存一份快照在本地文件中,優(yōu)先讀取。

阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)
這里我省略了比較多的細節(jié),如鑒權、負載均衡、高可用方面的設計(其實這部分才是真正值得學的,后邊另出文講吧),主要弄清客戶端與服務端的數據交互模式。

下邊我們以Nacos 2.0.1版本源碼分析,2.0以后的版本改動較多,和網上的很多資料略有些不同 地址:https://github.com/alibaba/nacos/releases/tag/2.0.1

客戶端源碼分析

Nacos配置中心的客戶端源碼在nacos-client項目,其中NacosConfigService實現類是所有操作的核心入口。

說之前先了解個客戶端數據結構cacheMap,這里大家重點記住它,因為它幾乎貫穿了Nacos客戶端的所有操作,由于存在多線程場景為保證數據一致性,cacheMap采用了AtomicReference原子變量實現。

/**
?*?groupKey?->?cacheData.
?*/

private?final?AtomicReference>?cacheMap?=?new?AtomicReference>(new?HashMap<>());

cacheMap是個Map結構,key為groupKey,是由dataId, group, tenant(租戶)拼接的字符串;value為CacheData對象,每個dataId都會持有一個CacheData對象。

獲取配置

Nacos獲取配置數據的邏輯比較簡單,先取本地快照文件中的配置,如果本地文件不存在或者內容為空,則再通過HTTP請求從遠端拉取對應dataId配置數據,并保存到本地快照中,請求默認重試3次,超時時間3s。

阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)
獲取配置有getConfig()getConfigAndSignListener()這兩個接口,但getConfig()只是發(fā)送普通的HTTP請求,而getConfigAndSignListener()則多了發(fā)起長輪詢和對dataId數據變更注冊監(jiān)聽的操作addTenantListenersWithContent()

@Override
public?String?getConfig(String?dataId,?String?group,?long?timeoutMs)?throws?NacosException?{
????return?getConfigInner(namespace,?dataId,?group,?timeoutMs);
}

@Override
public?String?getConfigAndSignListener(String?dataId,?String?group,?long?timeoutMs,?Listener?listener)
????????throws?NacosException?
{
????String?content?=?getConfig(dataId,?group,?timeoutMs);
????worker.addTenantListenersWithContent(dataId,?group,?content,?Arrays.asList(listener));
????return?content;
}
注冊監(jiān)聽

客戶端注冊監(jiān)聽,先從cacheMap中拿到dataId對應的CacheData對象。

public?void?addTenantListenersWithContent(String?dataId,?String?group,?String?content,
??????????????????????????????????????????List?listeners)
?throws?NacosException?
{
????group?=?blank2defaultGroup(group);
????String?tenant?=?agent.getTenant();
????//?1、獲取dataId對應的CacheData,如沒有則向服務端發(fā)起長輪詢請求獲取配置
????CacheData?cache?=?addCacheDataIfAbsent(dataId,?group,?tenant);
????synchronized?(cache)?{
????????//?2、注冊對dataId的數據變更監(jiān)聽
????????cache.setContent(content);
????????for?(Listener?listener?:?listeners)?{
????????????cache.addListener(listener);
????????}
????????cache.setSyncWithServer(false);
????????agent.notifyListenConfig();
????}
}
如沒有則向服務端發(fā)起長輪詢請求獲取配置,默認的Timeout時間為30s,并把返回的配置數據回填至CacheData對象的content字段,同時用content生成MD5值;再通過addListener()注冊監(jiān)聽器。

阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)
CacheData也是個出場頻率非常高的一個類,我們看到除了dataId、group、tenant、content這些相關的基礎屬性,還有幾個比較重要的屬性如:listeners、md5(content真實配置數據計算出來的md5值),以及注冊監(jiān)聽、數據比對、服務端數據變更通知操作都在這里。

阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)
其中listeners是對dataId所注冊的所有監(jiān)聽器集合,其中的ManagerListenerWrap對象除了持有Listener監(jiān)聽類,還有一個lastCallMd5字段,這個屬性很關鍵,它是判斷服務端數據是否更變的重要條件。

在添加監(jiān)聽的同時會將CacheData對象當前最新的md5值賦值給ManagerListenerWrap對象的lastCallMd5屬性。

public?void?addListener(Listener?listener)?{
????ManagerListenerWrap?wrap?=
????????(listener?instanceof?AbstractConfigChangeListener)???new?ManagerListenerWrap(listener,?md5,?content)
????????????:?new?ManagerListenerWrap(listener,?md5);
}
看到這對dataId監(jiān)聽設置就完事了?我們發(fā)現所有操作都圍著cacheMap結構中的CacheData對象,那么大膽猜測下一定會有專門的任務來處理這個數據結構。

阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)
變更通知

客戶端又是如何感知服務端數據已變更呢?

我們還是從頭看,NacosConfigService類的構造器中初始化了一個ClientWorker,而在ClientWorker類的構造器中又啟動了一個線程池來輪詢cacheMap。

阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)
而在executeConfigListen()方法中有這么一段邏輯,檢查cacheMap中dataId的CacheData對象內,MD5字段與注冊的監(jiān)聽listener內的lastCallMd5值,不相同表示配置數據變更則觸發(fā)safeNotifyListener方法,發(fā)送數據變更通知。

void?checkListenerMd5()?{
????for?(ManagerListenerWrap?wrap?:?listeners)?{
????????if?(!md5.equals(wrap.lastCallMd5))?{
????????????safeNotifyListener(dataId,?group,?content,?type,?md5,?encryptedDataKey,?wrap);
????????}
????}
}
safeNotifyListener()方法單獨起線程,向所有對dataId注冊過監(jiān)聽的客戶端推送變更后的數據內容。

阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)
客戶端接收通知,直接實現receiveConfigInfo()方法接收回調數據,處理自身業(yè)務就可以了。

configService.addListener(dataId,?group,?new?Listener()?{
????@Override
????public?void?receiveConfigInfo(String?configInfo)?{
????????System.out.println("receive:"? ?configInfo);
????}

????@Override
????public?Executor?getExecutor()?{
????????return?null;
????}
});
為了理解更直觀我用測試demo演示下,獲取服務端配置并設置監(jiān)聽,每當服務端配置數據變化,客戶端監(jiān)聽都會收到通知,一起看下效果。

public?static?void?main(String[]?args)?throws?NacosException,?InterruptedException?{
????String?serverAddr?=?"localhost";
????String?dataId?=?"test";
????String?group?=?"DEFAULT_GROUP";
????Properties?properties?=?new?Properties();
????properties.put("serverAddr",?serverAddr);
????ConfigService?configService?=?NacosFactory.createConfigService(properties);
????String?content?=?configService.getConfig(dataId,?group,?5000);
????System.out.println(content);
????configService.addListener(dataId,?group,?new?Listener()?{
????????@Override
????????public?void?receiveConfigInfo(String?configInfo)?{
????????????System.out.println("數據變更?receive:"? ?configInfo);
????????}
????????@Override
????????public?Executor?getExecutor()?{
????????????return?null;
????????}
????});

????boolean?isPublishOk?=?configService.publishConfig(dataId,?group,?"我是新配置內容~");
????System.out.println(isPublishOk);

????Thread.sleep(3000);
????content?=?configService.getConfig(dataId,?group,?5000);
????System.out.println(content);
}
結果和預想的一樣,當向服務端publishConfig數據變化后,客戶端可以立即感知,愣是用主動拉pull模式做出了服務端實時推送的效果。

數據變更?receive:我是新配置內容~
true
我是新配置內容~

服務端源碼分析

Nacos配置中心的服務端源碼主要在nacos-config項目的ConfigController類,服務端的邏輯要比客戶端稍復雜一些,這里我們重點看下。

處理長輪詢

服務端對外提供的監(jiān)聽接口地址/v1/cs/configs/listener,這個方法內容不多,順著doPollingConfig往下看。

阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)
服務端根據請求header中的Long-Pulling-Timeout屬性來區(qū)分請求是長輪詢還是短輪詢,這里咱們只關注長輪詢部分,接著看LongPollingService(記住這個service很關鍵)類中的addLongPollingClient()方法是如何處理客戶端的長輪詢請求的。

阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)
正??蛻舳四J設置的請求超時時間是30s,但這里我們發(fā)現服務端“偷偷”的給減掉了500ms,現在超時時間只剩下了29.5s,那為什么要這樣做呢?

用官方的解釋之所以要提前500ms響應請求,為了最大程度上保證客戶端不會因為網絡延時造成超時,考慮到請求可能在負載均衡時會耗費一些時間,畢竟Nacos最初就是按照阿里自身業(yè)務體量設計的嘛!

阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)
此時對客戶端提交上來的groupkey的MD5與服務端當前的MD5比對,如md5值不同,則說明服務端的配置項發(fā)生過變更,直接將該groupkey放入changedGroupKeys集合并返回給客戶端。

MD5Util.compareMd5(req,?rsp,?clientMd5Map)
如未發(fā)生變更,則將客戶端請求掛起,這個過程先創(chuàng)建一個名為ClientLongPolling的調度任務Runnable,并提交給scheduler定時線程池延后29.5s執(zhí)行。

ConfigExecutor.executeLongPolling(
????????????????new?ClientLongPolling(asyncContext,?clientMd5Map,?ip,?probeRequestSize,?timeout,?appName,?tag));
這里每個長輪詢任務攜帶了一個asyncContext對象,使得每個請求可以延遲響應,等延時到達或者配置有變更之后,調用asyncContext.complete()響應完成。

asyncContext 為 Servlet 3.0新增的特性,異步處理,使Servlet線程不再需要一直阻塞,等待業(yè)務處理完畢才輸出響應;可以先釋放容器分配給請求的線程與相關資源,減輕系統(tǒng)負擔,其響應將被延后,在處理完業(yè)務或者運算后再對客戶端進行響應。

阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)
ClientLongPolling任務被提交進入延遲線程池執(zhí)行的同時,服務端會通過一個allSubs隊列保存所有正在被掛起的客戶端長輪詢請求任務,這個是客戶端注冊監(jiān)聽的過程。

如延時期間客戶端據數一直未變化,延時時間到達后將本次長輪詢任務從allSubs隊列剔除,并響應請求response,這是取消監(jiān)聽。收到響應后客戶端再次發(fā)起長輪詢,循環(huán)往復。

阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)
處理長輪詢
到這我們知道服務端是如何掛起客戶端長輪詢請求的,一旦請求在掛起期間,用戶通過管理平臺操作了配置項,或者服務端收到了來自其他客戶端節(jié)點修改配置的請求。

怎么能讓對應已掛起的任務立即取消,并且及時通知客戶端數據發(fā)生了變更呢?

數據變更

管理平臺或者客戶端更改配置項接位置ConfigController中的publishConfig方法。

阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)
值得注意得是,在publishConfig接口中有這么一段邏輯,某個dataId配置數據被修改時會觸發(fā)一個數據變更事件Event

ConfigChangePublisher.notifyConfigChange(new?ConfigDataChangeEvent(false,?dataId,?group,?tenant,?time.getTime()));
仔細看LongPollingService會發(fā)現在它的構造方法中,正好訂閱了數據變更事件,并在事件觸發(fā)時執(zhí)行一個數據變更調度任務DataChangeTask。

阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)
訂閱數據變更事件
DataChangeTask內的主要邏輯就是遍歷allSubs隊列,上邊我們知道,這個隊列中維護的是所有客戶端的長輪詢請求任務,從這些任務中找到包含當前發(fā)生變更的groupkeyClientLongPolling任務,以此實現數據更變推送給客戶端,并從allSubs隊列中剔除此長輪詢任務。

阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)
DataChangeTask
而我們在看給客戶端響應response時,調用asyncContext.complete()結束了異步請求。

阿里面試這樣問:Nacos配置中心交互模型是?push?還是?pull??(原理 源碼分析)

結束語

上邊只揭開了nacos配置中心的冰山一角,實際上還有非常多重要的技術細節(jié)都沒提及到,建議大家沒事看看源碼,源碼不需要通篇的看,只要抓住核心部分就夠了。就比如今天這個題目以前我真沒太在意,突然被問一下子吃不準了,果斷看下源碼,而且這樣記憶比較深刻(別人嚼碎了喂你的知識總是比自己咀嚼的差那么點意思)。

nacos的源碼我個人覺得還是比較樸素的,代碼并沒有過多炫技,看起來相對輕松。大家不要對看源碼有什么抵觸,它也不過是別人寫的業(yè)務代碼而已,just so so!

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯系該專欄作者,如若文章內容侵犯您的權益,請及時聯系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或將催生出更大的獨角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數字化轉型技術解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關鍵字: AWS AN BSP 數字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術公司SODA.Auto推出其旗艦產品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關鍵字: 汽車 人工智能 智能驅動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據媒體報道,騰訊和網易近期正在縮減他們對日本游戲市場的投資。

關鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數據產業(yè)博覽會開幕式在貴陽舉行,華為董事、質量流程IT總裁陶景文發(fā)表了演講。

關鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數據產業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數字世界的話語權最終是由生態(tài)的繁榮決定的。

關鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經營業(yè)績穩(wěn)中有升 落實提質增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領增長 以科技創(chuàng)新為引領,提升企業(yè)核心競爭力 堅持高質量發(fā)展策略,塑強核心競爭優(yōu)勢...

關鍵字: 通信 BSP 電信運營商 數字經濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術學會聯合牽頭組建的NVI技術創(chuàng)新聯盟在BIRTV2024超高清全產業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現場 NVI技術創(chuàng)新聯...

關鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯合招商會上,軟通動力信息技術(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關鍵字: BSP 信息技術
關閉
關閉