精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Nacos配置中心交互模型是 Push 還是 Pull ?

開(kāi)發(fā) 前端
對(duì)于Nacos大家應(yīng)該都不太陌生,出身阿里名聲在外,能做動(dòng)態(tài)服務(wù)發(fā)現(xiàn)、配置管理,非常好用的一個(gè)工具。然而這樣的技術(shù)用的人越多面試被問(wèn)的概率也就越大,如果只停留在使用層面,那面試可能要吃大虧。

[[408988]]

本文轉(zhuǎn)載自微信公眾號(hào)「程序員內(nèi)點(diǎn)事」,作者程序員內(nèi)點(diǎn)事。轉(zhuǎn)載本文請(qǐng)聯(lián)系程序員內(nèi)點(diǎn)事公眾號(hào)。

大家好,我是小富~

對(duì)于Nacos大家應(yīng)該都不太陌生,出身阿里名聲在外,能做動(dòng)態(tài)服務(wù)發(fā)現(xiàn)、配置管理,非常好用的一個(gè)工具。然而這樣的技術(shù)用的人越多面試被問(wèn)的概率也就越大,如果只停留在使用層面,那面試可能要吃大虧。

比如我們今天要討論的話題,Nacos在做配置中心的時(shí)候,配置數(shù)據(jù)的交互模式是服務(wù)端推過(guò)來(lái)還是客戶端主動(dòng)拉的?

[[408989]]

這里我先拋出答案:客戶端主動(dòng)拉的!

接下來(lái)咱們扒一扒Nacos的源碼,來(lái)看看它具體是如何實(shí)現(xiàn)的?

配置中心

聊Nacos之前簡(jiǎn)單回顧下配置中心的由來(lái)。

簡(jiǎn)單理解配置中心的作用就是對(duì)配置統(tǒng)一管理,修改配置后應(yīng)用可以動(dòng)態(tài)感知,而無(wú)需重啟。

因?yàn)樵趥鹘y(tǒng)項(xiàng)目中,大多都采用靜態(tài)配置的方式,也就是把配置信息都寫(xiě)在應(yīng)用內(nèi)的yml或properties這類(lèi)文件中,如果要想修改某個(gè)配置,通常要重啟應(yīng)用才可以生效。

但有些場(chǎng)景下,比如我們想要在應(yīng)用運(yùn)行時(shí),通過(guò)修改某個(gè)配置項(xiàng),實(shí)時(shí)的控制某一個(gè)功能的開(kāi)閉,頻繁的重啟應(yīng)用肯定是不能接受的。

尤其是在微服務(wù)架構(gòu)下,我們的應(yīng)用服務(wù)拆分的粒度很細(xì),少則幾十多則上百個(gè)服務(wù),每個(gè)服務(wù)都會(huì)有一些自己特有或通用的配置。假如此時(shí)要改變通用配置,難道要我挨個(gè)改幾百個(gè)服務(wù)配置?很顯然這不可能。所以為了解決此類(lèi)問(wèn)題配置中心應(yīng)運(yùn)而生。

配置中心

推與拉模型

客戶端與配置中心的數(shù)據(jù)交互方式其實(shí)無(wú)非就兩種,要么推push,要么拉pull。

推模型

客戶端與服務(wù)端建立TCP長(zhǎng)連接,當(dāng)服務(wù)端配置數(shù)據(jù)有變動(dòng),立刻通過(guò)建立的長(zhǎng)連接將數(shù)據(jù)推送給客戶端。

優(yōu)勢(shì):長(zhǎng)鏈接的優(yōu)點(diǎn)是實(shí)時(shí)性,一旦數(shù)據(jù)變動(dòng),立即推送變更數(shù)據(jù)給客戶端,而且對(duì)于客戶端而言,這種方式更為簡(jiǎn)單,只建立連接接收數(shù)據(jù),并不需要關(guān)心是否有數(shù)據(jù)變更這類(lèi)邏輯的處理。

弊端:長(zhǎng)連接可能會(huì)因?yàn)榫W(wǎng)絡(luò)問(wèn)題,導(dǎo)致不可用,也就是俗稱的假死。連接狀態(tài)正常,但實(shí)際上已無(wú)法通信,所以要有的心跳機(jī)制KeepAlive來(lái)保證連接的可用性,才可以保證配置數(shù)據(jù)的成功推送。

拉模型

客戶端主動(dòng)的向服務(wù)端發(fā)請(qǐng)求拉配置數(shù)據(jù),常見(jiàn)的方式就是輪詢,比如每3s向服務(wù)端請(qǐng)求一次配置數(shù)據(jù)。

輪詢的優(yōu)點(diǎn)是實(shí)現(xiàn)比較簡(jiǎn)單。但弊端也顯而易見(jiàn),輪詢無(wú)法保證數(shù)據(jù)的實(shí)時(shí)性,什么時(shí)候請(qǐng)求?間隔多長(zhǎng)時(shí)間請(qǐng)求一次?都是不得不考慮的問(wèn)題,而且輪詢方式對(duì)服務(wù)端還會(huì)產(chǎn)生不小的壓力。

長(zhǎng)輪詢

開(kāi)篇我們就給出了答案,nacos采用的是客戶端主動(dòng)拉pull模型,應(yīng)用長(zhǎng)輪詢(Long Polling)的方式來(lái)獲取配置數(shù)據(jù)。

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

短輪詢

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

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

為了解決短輪詢的問(wèn)題,有了長(zhǎng)輪詢方案。

長(zhǎng)輪詢

長(zhǎng)輪詢可不是什么新技術(shù),它不過(guò)是由服務(wù)端控制響應(yīng)客戶端請(qǐng)求的返回時(shí)間,來(lái)減少客戶端無(wú)效請(qǐng)求的一種優(yōu)化手段,其實(shí)對(duì)于客戶端來(lái)說(shuō)與短輪詢的使用并沒(méi)有本質(zhì)上的區(qū)別。

客戶端發(fā)起請(qǐng)求后,服務(wù)端不會(huì)立即返回請(qǐng)求結(jié)果,而是將請(qǐng)求掛起等待一段時(shí)間,如果此段時(shí)間內(nèi)服務(wù)端數(shù)據(jù)變更,立即響應(yīng)客戶端請(qǐng)求,若是一直無(wú)變化則等到指定的超時(shí)時(shí)間后響應(yīng)請(qǐng)求,客戶端重新發(fā)起長(zhǎng)鏈接。

Nacos初識(shí)

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

直接執(zhí)行/bin/startup.X就可以了,默認(rèn)用戶密碼均是nacos。

幾個(gè)概念

Nacos配置中心的幾個(gè)核心概念:dataId、group、namespace,它們的層級(jí)關(guān)系如下圖:

dataId:是配置中心里最基礎(chǔ)的單元,它是一種key-value結(jié)構(gòu),key通常是我們的配置文件名稱,比如:application.yml、mybatis.xml,而value是整個(gè)文件下的內(nèi)容。

目前支持JSON、XML、YAML等多種配置格式。

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

namespace:項(xiàng)目開(kāi)發(fā)過(guò)程中肯定會(huì)有dev、test、pro等多個(gè)不同環(huán)境,namespace則是對(duì)不同環(huán)境進(jìn)行隔離,默認(rèn)所有配置都在public里。

架構(gòu)設(shè)計(jì)

下圖簡(jiǎn)要描述了nacos配置中心的架構(gòu)流程。

客戶端、控制臺(tái)通過(guò)發(fā)送Http請(qǐng)求將配置數(shù)據(jù)注冊(cè)到服務(wù)端,服務(wù)端持久化數(shù)據(jù)到Mysql。

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

這里我省略了比較多的細(xì)節(jié),如鑒權(quán)、負(fù)載均衡、高可用方面的設(shè)計(jì)(其實(shí)這部分才是真正值得學(xué)的,后邊另出文講吧),主要弄清客戶端與服務(wù)端的數(shù)據(jù)交互模式。

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

客戶端源碼分析

Nacos配置中心的客戶端源碼在nacos-client項(xiàng)目,其中NacosConfigService實(shí)現(xiàn)類(lèi)是所有操作的核心入口。

說(shuō)之前先了解個(gè)客戶端數(shù)據(jù)結(jié)構(gòu)cacheMap,這里大家重點(diǎn)記住它,因?yàn)樗鼛缀踟灤┝薔acos客戶端的所有操作,由于存在多線程場(chǎng)景為保證數(shù)據(jù)一致性,cacheMap采用了AtomicReference原子變量實(shí)現(xiàn)。

  1. /** 
  2.  * groupKey -> cacheData. 
  3.  */ 
  4. private final AtomicReference<Map<String, CacheData>> cacheMap = new AtomicReference<Map<String, CacheData>>(new HashMap<>()); 

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

獲取配置

Nacos獲取配置數(shù)據(jù)的邏輯比較簡(jiǎn)單,先取本地快照文件中的配置,如果本地文件不存在或者內(nèi)容為空,則再通過(guò)HTTP請(qǐng)求從遠(yuǎn)端拉取對(duì)應(yīng)dataId配置數(shù)據(jù),并保存到本地快照中,請(qǐng)求默認(rèn)重試3次,超時(shí)時(shí)間3s。

獲取配置有g(shù)etConfig()和getConfigAndSignListener()這兩個(gè)接口,但getConfig()只是發(fā)送普通的HTTP請(qǐng)求,而getConfigAndSignListener()則多了發(fā)起長(zhǎng)輪詢和對(duì)dataId數(shù)據(jù)變更注冊(cè)監(jiān)聽(tīng)的操作addTenantListenersWithContent()。

  1. @Override 
  2. public String getConfig(String dataId, String group, long timeoutMs) throws NacosException { 
  3.     return getConfigInner(namespace, dataId, group, timeoutMs); 
  4.  
  5. @Override 
  6. public String getConfigAndSignListener(String dataId, String group, long timeoutMs, Listener listener) 
  7.         throws NacosException { 
  8.     String content = getConfig(dataId, group, timeoutMs); 
  9.     worker.addTenantListenersWithContent(dataId, group, content, Arrays.asList(listener)); 
  10.     return content; 

注冊(cè)監(jiān)聽(tīng)

客戶端注冊(cè)監(jiān)聽(tīng),先從cacheMap中拿到dataId對(duì)應(yīng)的CacheData對(duì)象。

  1. public void addTenantListenersWithContent(String dataId, String group, String content, 
  2.                                           List<? extends Listener> listeners) throws NacosException { 
  3.     group = blank2defaultGroup(group); 
  4.     String tenant = agent.getTenant(); 
  5.     // 1、獲取dataId對(duì)應(yīng)的CacheData,如沒(méi)有則向服務(wù)端發(fā)起長(zhǎng)輪詢請(qǐng)求獲取配置 
  6.     CacheData cache = addCacheDataIfAbsent(dataId, group, tenant); 
  7.     synchronized (cache) { 
  8.         // 2、注冊(cè)對(duì)dataId的數(shù)據(jù)變更監(jiān)聽(tīng) 
  9.         cache.setContent(content); 
  10.         for (Listener listener : listeners) { 
  11.             cache.addListener(listener); 
  12.         } 
  13.         cache.setSyncWithServer(false); 
  14.         agent.notifyListenConfig(); 
  15.     } 

如沒(méi)有則向服務(wù)端發(fā)起長(zhǎng)輪詢請(qǐng)求獲取配置,默認(rèn)的Timeout時(shí)間為30s,并把返回的配置數(shù)據(jù)回填至CacheData對(duì)象的content字段,同時(shí)用content生成MD5值;再通過(guò)addListener()注冊(cè)監(jiān)聽(tīng)器。

CacheData也是個(gè)出場(chǎng)頻率非常高的一個(gè)類(lèi),我們看到除了dataId、group、tenant、content這些相關(guān)的基礎(chǔ)屬性,還有幾個(gè)比較重要的屬性如:listeners、md5(content真實(shí)配置數(shù)據(jù)計(jì)算出來(lái)的md5值),以及注冊(cè)監(jiān)聽(tīng)、數(shù)據(jù)比對(duì)、服務(wù)端數(shù)據(jù)變更通知操作都在這里。

其中l(wèi)isteners是對(duì)dataId所注冊(cè)的所有監(jiān)聽(tīng)器集合,其中的ManagerListenerWrap對(duì)象除了持有Listener監(jiān)聽(tīng)類(lèi),還有一個(gè)lastCallMd5字段,這個(gè)屬性很關(guān)鍵,它是判斷服務(wù)端數(shù)據(jù)是否更變的重要條件。

在添加監(jiān)聽(tīng)的同時(shí)會(huì)將CacheData對(duì)象當(dāng)前最新的md5值賦值給ManagerListenerWrap對(duì)象的lastCallMd5屬性。

  1. public void addListener(Listener listener) { 
  2.     ManagerListenerWrap wrap = 
  3.         (listener instanceof AbstractConfigChangeListener) ? new ManagerListenerWrap(listener, md5, content) 
  4.             : new ManagerListenerWrap(listener, md5); 

看到這對(duì)dataId監(jiān)聽(tīng)設(shè)置就完事了?我們發(fā)現(xiàn)所有操作都圍著cacheMap結(jié)構(gòu)中的CacheData對(duì)象,那么大膽猜測(cè)下一定會(huì)有專(zhuān)門(mén)的任務(wù)來(lái)處理這個(gè)數(shù)據(jù)結(jié)構(gòu)。

變更通知

客戶端又是如何感知服務(wù)端數(shù)據(jù)已變更呢?

我們還是從頭看,NacosConfigService類(lèi)的構(gòu)造器中初始化了一個(gè)ClientWorker,而在ClientWorker類(lèi)的構(gòu)造器中又啟動(dòng)了一個(gè)線程池來(lái)輪詢cacheMap。

而在executeConfigListen()方法中有這么一段邏輯,檢查cacheMap中dataId的CacheData對(duì)象內(nèi),MD5字段與注冊(cè)的監(jiān)聽(tīng)listener內(nèi)的lastCallMd5值,不相同表示配置數(shù)據(jù)變更則觸發(fā)safeNotifyListener方法,發(fā)送數(shù)據(jù)變更通知。

  1. void checkListenerMd5() { 
  2.     for (ManagerListenerWrap wrap : listeners) { 
  3.         if (!md5.equals(wrap.lastCallMd5)) { 
  4.             safeNotifyListener(dataId, group, content, type, md5, encryptedDataKey, wrap); 
  5.         } 
  6.     } 

safeNotifyListener()方法單獨(dú)起線程,向所有對(duì)dataId注冊(cè)過(guò)監(jiān)聽(tīng)的客戶端推送變更后的數(shù)據(jù)內(nèi)容。

客戶端接收通知,直接實(shí)現(xiàn)receiveConfigInfo()方法接收回調(diào)數(shù)據(jù),處理自身業(yè)務(wù)就可以了。

  1. configService.addListener(dataId, group, new Listener() { 
  2.     @Override 
  3.     public void receiveConfigInfo(String configInfo) { 
  4.         System.out.println("receive:" + configInfo); 
  5.     } 
  6.  
  7.     @Override 
  8.     public Executor getExecutor() { 
  9.         return null
  10.     } 
  11. }); 

為了理解更直觀我用測(cè)試demo演示下,獲取服務(wù)端配置并設(shè)置監(jiān)聽(tīng),每當(dāng)服務(wù)端配置數(shù)據(jù)變化,客戶端監(jiān)聽(tīng)都會(huì)收到通知,一起看下效果。

  1. public static void main(String[] args) throws NacosException, InterruptedException { 
  2.     String serverAddr = "localhost"
  3.     String dataId = "test"
  4.     String group = "DEFAULT_GROUP"
  5.     Properties properties = new Properties(); 
  6.     properties.put("serverAddr", serverAddr); 
  7.     ConfigService configService = NacosFactory.createConfigService(properties); 
  8.     String content = configService.getConfig(dataId, group, 5000); 
  9.     System.out.println(content); 
  10.     configService.addListener(dataId, group, new Listener() { 
  11.         @Override 
  12.         public void receiveConfigInfo(String configInfo) { 
  13.             System.out.println("數(shù)據(jù)變更 receive:" + configInfo); 
  14.         } 
  15.         @Override 
  16.         public Executor getExecutor() { 
  17.             return null
  18.         } 
  19.     }); 
  20.  
  21.     boolean isPublishOk = configService.publishConfig(dataId, group"我是新配置內(nèi)容~"); 
  22.     System.out.println(isPublishOk); 
  23.  
  24.     Thread.sleep(3000); 
  25.     content = configService.getConfig(dataId, group, 5000); 
  26.     System.out.println(content); 

結(jié)果和預(yù)想的一樣,當(dāng)向服務(wù)端publishConfig數(shù)據(jù)變化后,客戶端可以立即感知,愣是用主動(dòng)拉pull模式做出了服務(wù)端實(shí)時(shí)推送的效果。

  1. 數(shù)據(jù)變更 receive:我是新配置內(nèi)容~ 
  2. true 
  3. 我是新配置內(nèi)容~ 

服務(wù)端源碼分析

Nacos配置中心的服務(wù)端源碼主要在nacos-config項(xiàng)目的ConfigController類(lèi),服務(wù)端的邏輯要比客戶端稍復(fù)雜一些,這里我們重點(diǎn)看下。

處理長(zhǎng)輪詢

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

服務(wù)端根據(jù)請(qǐng)求header中的Long-Pulling-Timeout屬性來(lái)區(qū)分請(qǐng)求是長(zhǎng)輪詢還是短輪詢,這里咱們只關(guān)注長(zhǎng)輪詢部分,接著看LongPollingService(記住這個(gè)service很關(guān)鍵)類(lèi)中的addLongPollingClient()方法是如何處理客戶端的長(zhǎng)輪詢請(qǐng)求的。

正常客戶端默認(rèn)設(shè)置的請(qǐng)求超時(shí)時(shí)間是30s,但這里我們發(fā)現(xiàn)服務(wù)端“偷偷”的給減掉了500ms,現(xiàn)在超時(shí)時(shí)間只剩下了29.5s,那為什么要這樣做呢?

用官方的解釋之所以要提前500ms響應(yīng)請(qǐng)求,為了最大程度上保證客戶端不會(huì)因?yàn)榫W(wǎng)絡(luò)延時(shí)造成超時(shí),考慮到請(qǐng)求可能在負(fù)載均衡時(shí)會(huì)耗費(fèi)一些時(shí)間,畢竟Nacos最初就是按照阿里自身業(yè)務(wù)體量設(shè)計(jì)的嘛!

此時(shí)對(duì)客戶端提交上來(lái)的groupkey的MD5與服務(wù)端當(dāng)前的MD5比對(duì),如md5值不同,則說(shuō)明服務(wù)端的配置項(xiàng)發(fā)生過(guò)變更,直接將該groupkey放入changedGroupKeys集合并返回給客戶端。

  1. MD5Util.compareMd5(req, rsp, clientMd5Map) 

如未發(fā)生變更,則將客戶端請(qǐng)求掛起,這個(gè)過(guò)程先創(chuàng)建一個(gè)名為ClientLongPolling的調(diào)度任務(wù)Runnable,并提交給scheduler定時(shí)線程池延后29.5s執(zhí)行。

  1. ConfigExecutor.executeLongPolling( 
  2.                 new ClientLongPolling(asyncContext, clientMd5Map, ip, probeRequestSize, timeout, appName, tag)); 

這里每個(gè)長(zhǎng)輪詢?nèi)蝿?wù)攜帶了一個(gè)asyncContext對(duì)象,使得每個(gè)請(qǐng)求可以延遲響應(yīng),等延時(shí)到達(dá)或者配置有變更之后,調(diào)用asyncContext.complete()響應(yīng)完成。

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

ClientLongPolling任務(wù)被提交進(jìn)入延遲線程池執(zhí)行的同時(shí),服務(wù)端會(huì)通過(guò)一個(gè)allSubs隊(duì)列保存所有正在被掛起的客戶端長(zhǎng)輪詢請(qǐng)求任務(wù),這個(gè)是客戶端注冊(cè)監(jiān)聽(tīng)的過(guò)程。

如延時(shí)期間客戶端據(jù)數(shù)一直未變化,延時(shí)時(shí)間到達(dá)后將本次長(zhǎng)輪詢?nèi)蝿?wù)從allSubs隊(duì)列剔除,并響應(yīng)請(qǐng)求response,這是取消監(jiān)聽(tīng)。收到響應(yīng)后客戶端再次發(fā)起長(zhǎng)輪詢,循環(huán)往復(fù)。

處理長(zhǎng)輪詢

到這我們知道服務(wù)端是如何掛起客戶端長(zhǎng)輪詢請(qǐng)求的,一旦請(qǐng)求在掛起期間,用戶通過(guò)管理平臺(tái)操作了配置項(xiàng),或者服務(wù)端收到了來(lái)自其他客戶端節(jié)點(diǎn)修改配置的請(qǐng)求。

怎么能讓對(duì)應(yīng)已掛起的任務(wù)立即取消,并且及時(shí)通知客戶端數(shù)據(jù)發(fā)生了變更呢?

數(shù)據(jù)變更

管理平臺(tái)或者客戶端更改配置項(xiàng)接位置ConfigController中的publishConfig方法。

值得注意得是,在publishConfig接口中有這么一段邏輯,某個(gè)dataId配置數(shù)據(jù)被修改時(shí)會(huì)觸發(fā)一個(gè)數(shù)據(jù)變更事件Event。

  1. ConfigChangePublisher.notifyConfigChange(new ConfigDataChangeEvent(false, dataId, group, tenant, time.getTime())); 

仔細(xì)看LongPollingService會(huì)發(fā)現(xiàn)在它的構(gòu)造方法中,正好訂閱了數(shù)據(jù)變更事件,并在事件觸發(fā)時(shí)執(zhí)行一個(gè)數(shù)據(jù)變更調(diào)度任務(wù)DataChangeTask。

訂閱數(shù)據(jù)變更事件

DataChangeTask內(nèi)的主要邏輯就是遍歷allSubs隊(duì)列,上邊我們知道,這個(gè)隊(duì)列中維護(hù)的是所有客戶端的長(zhǎng)輪詢請(qǐng)求任務(wù),從這些任務(wù)中找到包含當(dāng)前發(fā)生變更的groupkey的ClientLongPolling任務(wù),以此實(shí)現(xiàn)數(shù)據(jù)更變推送給客戶端,并從allSubs隊(duì)列中剔除此長(zhǎng)輪詢?nèi)蝿?wù)。

DataChangeTask

而我們?cè)诳唇o客戶端響應(yīng)response時(shí),調(diào)用asyncContext.complete()結(jié)束了異步請(qǐng)求。

結(jié)束語(yǔ)

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

nacos的源碼我個(gè)人覺(jué)得還是比較樸素的,代碼并沒(méi)有過(guò)多炫技,看起來(lái)相對(duì)輕松。大家不要對(duì)看源碼有什么抵觸,它也不過(guò)是別人寫(xiě)的業(yè)務(wù)代碼而已,just so so!

 

責(zé)任編輯:武曉燕 來(lái)源: 程序員內(nèi)點(diǎn)事
相關(guān)推薦

2023-11-17 09:02:51

Nacos配置中心

2021-06-10 06:57:39

Nacos配置模塊

2021-08-09 07:58:36

Nacos 服務(wù)注冊(cè)源碼分析

2022-06-13 09:58:06

NacosSpring

2024-12-10 08:27:28

2021-09-02 09:51:32

監(jiān)控系統(tǒng)分布式

2022-08-29 06:27:15

Nacos微服務(wù)

2021-06-29 07:04:38

Nacos服務(wù)配置

2022-08-30 22:12:19

Nacos組件服務(wù)注冊(cè)

2018-11-15 15:03:59

安全運(yùn)營(yíng)中心SOC數(shù)據(jù)泄露

2021-08-02 07:35:19

Nacos配置中心namespace

2023-08-03 08:51:07

2025-03-03 10:27:33

配置中心微服務(wù)架構(gòu)

2023-10-16 16:14:32

數(shù)據(jù)中心

2021-02-10 09:54:15

分布式NacosApollo

2022-05-09 11:15:05

RocketMQPULL 模式PUSH 模式

2012-08-13 10:52:20

控制數(shù)據(jù)中心

2015-11-27 14:39:26

數(shù)據(jù)中心擴(kuò)張計(jì)劃

2024-09-03 15:57:41

2023-03-01 08:15:10

NginxNacos
點(diǎn)贊
收藏

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

亚洲欧美综合7777色婷婷| 大西瓜av在线| 在线永久看片免费的视频| 自拍偷拍一区| 欧美精品丝袜中出| 亚洲精品少妇一区二区| 日本一区视频| 激情小说亚洲一区| 88国产精品欧美一区二区三区| 手机免费看av| 日韩中文字幕视频网| 精品福利在线看| 一区二区不卡视频| 天堂网在线资源| 久久国产尿小便嘘嘘| 97视频免费在线看| 久久噜噜色综合一区二区| 免费成人三级| 日韩午夜激情电影| 9久久婷婷国产综合精品性色 | 爱情电影网av一区二区| 午夜国产不卡在线观看视频| 伊人精品久久久久7777| 色中色在线视频| 国产99久久久国产精品免费看| 国产精品视频自拍| 欧美精品一二三四区| 欧美日本三区| 伊人一区二区三区久久精品| 国产白嫩美女无套久久| 日韩精品一区二区三区免费视频| 在线视频一区二区免费| 青娱乐自拍偷拍| 午夜在线激情影院| 中文字幕一区日韩精品欧美| 欧美一区二区视频在线| 天天摸天天碰天天爽天天弄| 国产99久久久国产精品| 91精品国产99久久久久久红楼| 亚洲一级在线播放| 日韩高清国产一区在线| 奇门遁甲1982国语版免费观看高清| 欧美精品久久久久性色| 在线看片不卡| 久久精品中文字幕一区| 国产精品av久久久久久无| 免费视频一区三区| 国产视频精品免费播放| 久久人妻少妇嫩草av无码专区| av成人app永久免费| 日韩一级高清毛片| 99热这里只有精品2| 欧美高清一级片| 制服丝袜日韩国产| 1314成人网| 日韩一二三区在线观看| 日韩欧美国产三级| 潘金莲一级淫片aaaaa| 日韩在线网址| 亚洲国产美女久久久久 | 久久精品亚洲国产奇米99| 国产精品jizz视频| 视频污在线观看| 91美女在线观看| 欧洲成人一区二区| 999在线视频| 国产精品久久久久久久第一福利| 一区二区三区偷拍| 4438x成人网全国最大| 亚洲免费在线电影| 免费特级黄色片| 亚洲淫成人影院| 欧美亚洲动漫制服丝袜| 国产美女18xxxx免费视频| 久久伊人影院| 亚洲国产日韩欧美在线图片| 黄瓜视频污在线观看| jlzzjlzz亚洲女人| 美女av一区二区| 日产精品久久久久| 天堂久久一区二区三区| 国产中文欧美精品| 蜜臀av午夜精品| 久久免费视频一区| 三年中文高清在线观看第6集 | 热久久免费国产视频| 久久国产香蕉视频| 国产河南妇女毛片精品久久久| 国产精品香蕉视屏| 成人免费黄色网页| 一区二区在线免费| 日本在线观看a| 国产精品美女久久久久人| 亚洲第一免费网站| 毛片aaaaaa| 在线精品福利| 国产精品欧美亚洲777777| 国产99久一区二区三区a片| 99久久国产免费看| 麻豆中文字幕在线观看| 国产中文在线播放| 欧美精品电影在线播放| 国产麻豆xxxvideo实拍| 99久久精品网| 91高潮在线观看| 99久久一区二区| 久久精品视频免费观看| 美女黄色免费看| 国产精品伦一区二区| 亚洲激情 国产| 翔田千里88av中文字幕| 天堂成人国产精品一区| 国产精品二区三区| 日本高清在线观看wwwww色| 婷婷亚洲久悠悠色悠在线播放| 国产精品嫩草影院8vv8 | 国产成人综合在线| 神马影院一区二区| 麻豆视频在线看| 欧美不卡一二三| 在线日韩国产网站| 日韩精品欧美成人高清一区二区| 国产精品视频500部| 国产精品一卡二卡三卡| 欧美视频在线观看一区二区| 日本三级日本三级日本三级极| 亚洲啊v在线观看| 国产精品久久久av| 日韩永久免费视频| 亚洲一区在线看| theporn国产精品| 日韩免费特黄一二三区| 日本欧美国产在线| 午夜视频在线免费播放| 亚洲午夜av在线| 制服.丝袜.亚洲.中文.综合懂| 99久久亚洲精品蜜臀| 国产精品稀缺呦系列在线| 狠狠v欧美ⅴ日韩v亚洲v大胸 | 中文字幕在线不卡一区| 美女黄色片视频| 欧美日韩国产在线观看网站 | 久久夜色撩人精品| 国产精品久久久久久免费播放| 欧美国产成人精品| 国产一级特黄a大片免费| 精品国产91| 国产精品视频专区| 久草中文在线| 日韩欧美你懂的| 国产亚洲小视频| 白白色亚洲国产精品| 欧美 日韩 亚洲 一区| 免费福利视频一区| 日本精品视频在线观看| 黄色电影免费在线看| 在线亚洲+欧美+日本专区| 粉嫩精品久久99综合一区| 免费观看成人av| 在线观看国产一区| 国产一区二区| 欧美劲爆第一页| 亚洲区小说区图片区| 日本韩国欧美一区二区三区| 超薄肉色丝袜一二三| 久久99精品视频| 国产精品视频二| 麻豆一区二区| 国产精品电影观看| 成人三级网址| 亚洲成人黄色在线观看| 日韩一级在线视频| 中文字幕中文字幕一区二区| 天天色天天干天天色| 亚洲视频久久| 欧美一区二区三区电影在线观看| 久久99国产精品二区高清软件| 久久精品一本久久99精品| 日本免费一区视频| 91福利精品第一导航| 182在线观看视频| av影院午夜一区| 中文字幕第36页| 国产精品a久久久久| 欧美乱偷一区二区三区在线| 欧美日韩破处视频| 91国语精品自产拍在线观看性色| 国产高清一区在线观看| 欧美一区二区三级| 精品国产xxx| 亚洲免费伊人电影| 日韩乱码人妻无码中文字幕久久| 国产一区二区三区免费看 | 亚洲欧洲精品在线观看| 高清一区二区三区| 国产精品亚洲一区二区三区| 激情网站在线| 中文字幕亚洲无线码在线一区| 丰满人妻一区二区三区免费视频 | 999香蕉视频| 一区二区日韩欧美| 欧美日韩日本网| 7777精品| 成人日韩av在线| 精品3atv在线视频| 国内久久久精品| 日本黄色片在线观看| 亚洲乱码一区av黑人高潮| 国产av一区二区三区| 在线精品国精品国产尤物884a| 国产精品九九九九九九| 中文字幕av免费专区久久| 强迫凌虐淫辱の牝奴在线观看| 麻豆91精品91久久久的内涵| 一区二区传媒有限公司| 亚洲欧美偷拍自拍| 五月天国产一区| 日韩高清电影免费| 成人3d动漫一区二区三区91| 欧美亚洲二区| 国产精品精品视频| 亚洲人成在线网站| 久久久久久久久久久久久久久久久久av| 2017亚洲天堂1024| 亚洲色图在线观看| 日韩电影在线观看完整版| 欧美xxxx老人做受| www.精品久久| 欧美一区二区女人| 国产精品久久久久毛片| 欧美日韩成人高清| 中文字幕乱码一区二区| 色丁香久综合在线久综合在线观看 | 日本一区福利在线| 国产精品播放| 粉嫩精品导航导航| 国产亚洲二区| 欧美黑人巨大videos精品| 国产视频一区二区不卡| 成人盗摄视频| 国产亚洲欧美一区二区| 大香伊人久久精品一区二区| 成人欧美一区二区三区视频| 51亚洲精品| 国产精品12| 成人爽a毛片免费啪啪红桃视频| 97超碰人人看人人| 成人偷拍自拍| 久久www免费人成精品| 你懂的在线观看一区二区| 精品亚洲第一| 亚洲欧美成人vr| 日韩欧美一区二区三区四区| 精品国产乱码久久久久久1区2匹| 日本不卡高清视频一区| 精品国产精品久久一区免费式| 先锋影音欧美| 91精品国产福利在线观看麻豆| 麻豆视频传媒入口| 亚洲午夜91| 成人综合视频在线| 日日夜夜一区二区| 欧美特级aaa| 国产精品66部| www.免费av| 久久亚洲综合色一区二区三区| 一级黄色性视频| 18欧美亚洲精品| 久青草免费视频| 欧美日韩综合视频| 五月激情丁香网| 91精品婷婷国产综合久久| 精品人妻一区二区三区三区四区 | 日韩午夜黄色| 一级在线免费视频| 久久国产乱子精品免费女| 亚洲制服在线观看| www.久久久久久久久| 国产伦理片在线观看| 亚洲情趣在线观看| 久久久久久久久久久久久久av| 日本黄色一区二区| 国产99对白在线播放| 亚洲精品一区在线观看香蕉| 日本蜜桃在线观看| 7m精品福利视频导航| 亚洲欧洲一二区| 久久精品国产理论片免费| 日韩一级毛片| 女性女同性aⅴ免费观女性恋| 蜜臀久久久久久久| 国产激情第一页| 中文字幕一区二区三区不卡在线| 日韩精品无码一区二区| 欧美日韩美少妇| 三级网站免费观看| 色777狠狠综合秋免鲁丝| 俺来俺也去www色在线观看| 国产精品福利久久久| 中文在线免费一区三区| 色播五月综合| 99在线|亚洲一区二区| 一级黄色录像在线观看| 91网上在线视频| 欧美激情国产精品免费| 欧美日韩三级一区| 偷拍25位美女撒尿视频在线观看| 日韩有码在线电影| 电影一区二区三区| 国产精品入口免费| 91精品国产自产在线观看永久∴| 91精品91久久久中77777老牛| 国产九色精品成人porny | 日韩一区欧美一区| 日韩色图在线观看| 精品国产乱码久久久久久闺蜜 | 中文字幕第17页| 久久久久国产成人精品亚洲午夜| 69xx绿帽三人行| 欧美午夜在线观看| 欧洲天堂在线观看| 97婷婷涩涩精品一区| 最新国产一区二区| ijzzijzzij亚洲大全| 麻豆精品一区二区三区| 国产又粗又猛又爽视频| 欧美日韩在线视频一区| 高h调教冰块play男男双性文| 美女精品视频一区| japansex久久高清精品| 中文字幕久久综合| 另类的小说在线视频另类成人小视频在线 | 成人在线中文| 日韩亚洲视频在线| 日本大胆欧美人术艺术动态 | 亚洲欧美成aⅴ人在线观看| 伊人网免费视频| 伊人伊成久久人综合网站 | 99精品99久久久久久宅男| 91欧美大片| 久久久久xxxx| 自拍偷拍亚洲综合| 国产精品一品二区三区的使用体验| 在线看福利67194| 福利精品在线| 亚洲综合欧美日韩| 激情都市一区二区| 国产男女猛烈无遮挡在线喷水| 正在播放亚洲一区| 91高清在线观看视频| av在线不卡观看| 国自产拍偷拍福利精品免费一| 91精品人妻一区二区三区蜜桃2| 亚洲另类在线一区| 亚洲第一成年人网站| 久久久亚洲国产| 欧美久久香蕉| 自拍偷拍 国产| 成人欧美一区二区三区小说| av免费在线不卡| 久久久久久久色| 色综合久久中文| 九色porny91| 综合欧美一区二区三区| 亚洲大尺度视频| 欧美在线性视频| 成人3d动漫在线观看| 亚洲精品免费一区亚洲精品免费精品一区| 日韩一区中文字幕| 老熟妇高潮一区二区高清视频| 91av国产在线| 色97色成人| 95视频在线观看| 在线视频国产一区| 国产三级在线播放| 精品视频导航| 久久se这里有精品| 精品在线视频免费观看| 亚洲人成网站777色婷婷| 四虎成人精品一区二区免费网站| 成人av在线播放观看| 久久久久久9999| 国产男女无套免费网站| 久久久亚洲福利精品午夜| 日韩成人精品一区| 久草免费资源站| 欧美视频在线观看一区二区| 久久免费电影| 日韩国产精品一区二区三区| 国产一区二区免费在线| 黄色在线免费观看| 欧美成人精品在线观看| 亚瑟一区二区三区四区| 天美一区二区三区| 欧美性猛xxx| 影音先锋男人资源在线| 日韩av高清| 成人动漫一区二区| 一区二区视频播放| 91成人精品网站|