日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
聊聊對(duì)Nacos Client服務(wù)發(fā)現(xiàn)源碼分析

本文轉(zhuǎn)載自微信公眾號(hào)「程序新視界」,作者二師兄。轉(zhuǎn)載本文請(qǐng)聯(lián)系程序新視界公眾號(hào)。

藍(lán)田網(wǎng)站建設(shè)公司成都創(chuàng)新互聯(lián)公司,藍(lán)田網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為藍(lán)田上1000+提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)網(wǎng)站制作要多少錢,請(qǐng)找那個(gè)售后服務(wù)好的藍(lán)田做網(wǎng)站的公司定做!

學(xué)習(xí)不用那么功利,二師兄帶你從更高維度輕松閱讀源碼~

本篇帶大家通過(guò)源碼層面分析一下Nacos Client的服務(wù)發(fā)現(xiàn)的路程,事實(shí)可能并不像你想象的那樣簡(jiǎn)單。

Nacos服務(wù)發(fā)現(xiàn)

直觀的看,Nacos客戶端的服務(wù)發(fā)現(xiàn),就是封裝參數(shù)、調(diào)用服務(wù)端接口、獲得返回實(shí)例列表。

naocos

但細(xì)化這個(gè)流程,會(huì)發(fā)現(xiàn)不僅包括了通過(guò)NamingService獲取服務(wù)列表,在獲取服務(wù)列表的過(guò)程中還涉及到通信協(xié)議(Http or gRPC)、訂閱流程、故障轉(zhuǎn)移邏輯等。下面我們根據(jù)服務(wù)發(fā)現(xiàn)來(lái)捋一下相關(guān)的流程。

先說(shuō)入口程序,依舊是在NamingTest中可以看到:

 
 
 
 
  1. NamingService namingService = NacosFactory.createNamingService(properties); 
  2. namingService.registerInstance("nacos.test.1", instance); 
  3.  
  4. ThreadUtils.sleep(5000L); 
  5. // 獲取實(shí)例列表 
  6. List list = namingService.getAllInstances("nacos.test.1"); 

關(guān)于NamingService的實(shí)例化和基本功能,在服務(wù)注冊(cè)時(shí)已經(jīng)講過(guò),這里直接看獲取實(shí)例列表方法getAllInstances。該方法的參數(shù)就是服務(wù)的名稱。

經(jīng)過(guò)一些列的重載方法調(diào)用,真正處理核心邏輯的方法如下:

 
 
 
 
  1. @Override 
  2. public List getAllInstances(String serviceName, String groupName, List clusters, 
  3.         boolean subscribe) throws NacosException { 
  4.     ServiceInfo serviceInfo; 
  5.     String clusterString = StringUtils.join(clusters, ","); 
  6.     // 是否訂閱模式 
  7.     if (subscribe) { 
  8.         // 先從客戶端緩存獲取服務(wù)信息 
  9.         serviceInfo = serviceInfoHolder.getServiceInfo(serviceName, groupName, clusterString); 
  10.         if (null == serviceInfo) { 
  11.             // 如果本地緩存不存在服務(wù)信息,則進(jìn)行訂閱 
  12.             serviceInfo = clientProxy.subscribe(serviceName, groupName, clusterString); 
  13.         } 
  14.     } else { 
  15.         // 如果未訂閱服務(wù)信息,則直接從服務(wù)器進(jìn)行查詢 
  16.         serviceInfo = clientProxy.queryInstancesOfService(serviceName, groupName, clusterString, 0, false); 
  17.     } 
  18.     // 從服務(wù)信息中獲去實(shí)例列表 
  19.     List list; 
  20.     if (serviceInfo == null || CollectionUtils.isEmpty(list = serviceInfo.getHosts())) { 
  21.         return new ArrayList(); 
  22.     } 
  23.     return list; 

首先看重載的getAllInstances方法,比入口方法多了幾個(gè)參數(shù),這里不僅有服務(wù)名稱,還有分組名稱(groupName)、集群列表(clusters)、是否訂閱(subscribe)。

重載方法中的其他參數(shù)已經(jīng)設(shè)置了默認(rèn)值。比如,分組名稱默認(rèn)為“DEFAULT_GROUP”、集群列表默認(rèn)為空數(shù)組、是否訂閱默認(rèn)為“訂閱”。

上述方法整理成流程圖如下:

naocos

上述流程的基本邏輯為:

如果是訂閱模式,則直接從本地緩存獲取服務(wù)信息(ServiceInfo),然后從中獲取實(shí)例列表,這是因?yàn)橛嗛啓C(jī)制會(huì)自動(dòng)同步服務(wù)器實(shí)例的變化到本地。如果本地緩存中沒(méi)有,那說(shuō)明是首次調(diào)用,則進(jìn)行訂閱,在訂閱完成后會(huì)獲得到服務(wù)信息。

如果是非訂閱模式,那就直接請(qǐng)求服務(wù)器端,獲得服務(wù)信息。

訂閱處理流程

在上述流程中,涉及到了訂閱邏輯,入口代碼為獲取實(shí)例列表中的如下方法:

 
 
 
 
  1. serviceInfo = clientProxy.subscribe(serviceName, groupName, clusterString); 

下面就來(lái)看看該方法內(nèi)部是如何進(jìn)行處理的。首先,這里的clientProxy是NamingClientProxy類的對(duì)象。對(duì)應(yīng)的subscribe實(shí)現(xiàn)如下:

 
 
 
 
  1. @Override 
  2. public ServiceInfo subscribe(String serviceName, String groupName, String clusters) throws NacosException { 
  3.     String serviceNameWithGroup = NamingUtils.getGroupedName(serviceName, groupName); 
  4.     String serviceKey = ServiceInfo.getKey(serviceNameWithGroup, clusters); 
  5.     // 獲取緩存中的ServiceInfo 
  6.     ServiceInfo result = serviceInfoHolder.getServiceInfoMap().get(serviceKey); 
  7.     if (null == result) { 
  8.         // 如果為null,則進(jìn)行訂閱邏輯處理,基于gRPC協(xié)議 
  9.         result = grpcClientProxy.subscribe(serviceName, groupName, clusters); 
  10.     } 
  11.     // 定時(shí)調(diào)度UpdateTask 
  12.     serviceInfoUpdateService.scheduleUpdateIfAbsent(serviceName, groupName, clusters); 
  13.     // ServiceInfo本地緩存處理 
  14.     serviceInfoHolder.processServiceInfo(result); 
  15.     return result; 

在上述代碼中,可以看到在獲取服務(wù)實(shí)例列表時(shí)(特別是首次),也進(jìn)行了訂閱邏輯的拓展,基本流程圖如下:

naocos

上圖流程中可以看出,訂閱方法先通過(guò)代理類進(jìn)行了本地緩存的判斷,如果本地緩存存在ServiceInfo信息,則直接返回。如果不存在,則默認(rèn)采用gRPC協(xié)議進(jìn)行訂閱,并返回ServiceInfo。

grpcClientProxy的subscribe訂閱方法就是直接向服務(wù)器發(fā)送了一個(gè)訂閱請(qǐng)求,并返回結(jié)果,就沒(méi)有做過(guò)多處理了。

訂閱完成之后,會(huì)通過(guò)ServiceInfoUpdateService開(kāi)啟一個(gè)定時(shí)任務(wù),這個(gè)定時(shí)任務(wù)主要的作用就是來(lái)定時(shí)同步服務(wù)器端的實(shí)例列表信息,并進(jìn)行本地緩存更新等操作。

最后一步,ServiceInfo本地緩存處理。這里會(huì)將獲得的最新ServiceInfo與本地內(nèi)存中的ServiceInfo進(jìn)行比較,更新,發(fā)布變更時(shí)間,磁盤文件存儲(chǔ)等操作。其實(shí),這一步的操作,在訂閱定時(shí)任務(wù)中也進(jìn)行了處理。

關(guān)于訂閱細(xì)節(jié)和本地緩存處理,涉及內(nèi)容較多,我們后面單獨(dú)拓展開(kāi)講解。這里知道整體流程即可。

小結(jié)

本文主要梳理了Nacos客戶端服務(wù)發(fā)現(xiàn)的核心流程,包括:

第一,如果沒(méi)有開(kāi)啟訂閱模式,則直接通過(guò)/instance/list接口(默認(rèn)通過(guò)gRPC協(xié)議)獲取服務(wù)實(shí)例列表信息;

第二,如果開(kāi)啟訂閱模式(默認(rèn)開(kāi)啟),則先會(huì)從本地緩存中獲取實(shí)例信息,如果不存在,則進(jìn)行訂閱獲并獲取實(shí)例信息;

第三,在開(kāi)啟訂閱時(shí),會(huì)開(kāi)啟定時(shí)任務(wù),定時(shí)執(zhí)行UpdateTask(獲取服務(wù)器實(shí)例信息、更新本地緩存、發(fā)布事件);

第四,在第二步獲得最新的實(shí)例信息之后,也會(huì)執(zhí)行processServiceInfo方法來(lái)更新內(nèi)存和本地實(shí)例緩存,并發(fā)布變更時(shí)間。

第五,至此,與第二步形成循環(huán),每次獲取本地緩存,不存在則更新……

關(guān)于用來(lái)處理訂閱相關(guān)的UpdateTask和用來(lái)處理本地緩存的ServiceInfoHolder#processServiceInfo方法,我們后面文章繼續(xù)講解。


名稱欄目:聊聊對(duì)Nacos Client服務(wù)發(fā)現(xiàn)源碼分析
文章起源:http://www.5511xx.com/article/coooccd.html