天天看點

Nacos源碼分析(五)用戶端服務發現原理分析

作者:愛好程式設計的程式員老徐

上幾篇文章我主要分析了Nacos用戶端和服務端的注冊流程,本節我主要分析Nacos服務發現源碼,主要分為兩部分分析,一部分是用戶端源碼一部分是服務端源碼分析,廢話不多說直接進入正題,Nacos源碼提供了一個測試類叫NamingExample,順着這個類進行源碼分析,我的代碼截圖如下:

Nacos源碼分析(五)用戶端服務發現原理分析

NamingExample的main方法截圖

從截圖可以看出依次調用了NamingService的registerInstance方法,該方法實際上就是注冊執行個體方法,下面的getAllInstances方法就是服務發現的源碼,我們順着這個方法進行分析。該方法調了幾個重載方法,最終調用到了四個參數的getAllInstances方法,該方法截圖如下:

Nacos源碼分析(五)用戶端服務發現原理分析

NacosNamingService類的getAllInstances方法截圖

該方法有四個入參參數,serviceName服務名稱,groupName分組名稱,如果不傳預設是DEFAULT_GROUP分組,clusters預設為空集合,subscribe指定訂閱模式是true,判斷subscribe值是否為true,本例子中是true,調用HostReactor的getServiceInfo方法,該方法截圖如下:

Nacos源碼分析(五)用戶端服務發現原理分析

HostReactor的getServiceInfo方法截圖

該方法主要是從serviceInfoMap的map資料結構中根據key的值是分組名稱+@@+服務名稱,以下簡稱serviceName,查詢ServiceInfo,第一次進來serviceObj為null,建立一個ServiceInfo對象,該對象參數主要是serviceName和clusters,建立以後放入到serviceInfoMap代表的map資料結構中,往updatingMap資料結構的map中放入一個key是serviceName,value是一個Object對象,我們看到else if分支中有判斷updatingMap中是否包含serviceName,如果有說明有至少2個用戶端同時請求擷取執行個體對象,此時其餘用戶端會加鎖等待先處理的用戶端處理完成以後調用serviceObj.notifyAll()方法直接從

serviceInfoMap中的Map結構中擷取新執行個體而不需要每個用戶端都去伺服器端擷取執行個體提高了性能。接着調用updateServiceNow方法,該方法主要是請求伺服器端擷取json執行個體,然後處理傳回的json執行個體,該方法截圖如下:

Nacos源碼分析(五)用戶端服務發現原理分析

HostReactor類的updateService方法截圖

判斷result如果不為空調用processServiceJson方法處理傳回的json執行個體,該方法截圖如下:

Nacos源碼分析(五)用戶端服務發現原理分析

HostReactor類的processServiceJson方法截圖一

Nacos源碼分析(五)用戶端服務發現原理分析

HostReactor類的processServiceJson方法截圖二

Nacos源碼分析(五)用戶端服務發現原理分析

HostReactor類的processServiceJson方法截圖三

首先把json資料轉為ServiceInfo對象,該對象中包含了執行個體Instance集合,即是已經注冊在伺服器端的執行個體集合,從serviceInfoMap根據servieName取出ServiceInfo對象,該對象現在隻有serviceName屬性和clusters屬性,稱為老的ServiceInfo對象,然後把serviceInfoMap中的value替換成json轉換後的ServiceInfo對象,然後釋出一個InstancesChangeEvent事件,關于事件的機制我會在以後的文章中進行分析,所有的都處理完成傳回到updateService方法會執行finally語句塊ServiceInfo.notifyAll()方法,前面已經說過,通知其他用戶端擷取新執行個體對象不需要其他用戶端再去伺服器端進行請求擷取,至此用戶端服務發現源碼就分析完了。

總結:

用戶端擷取伺服器端執行個體源碼比較簡單,主要就是根據serviceName服務名,namespace空間id等參數去伺服器中擷取執行個體集合然後傳回給用戶端,在這其中可能會有多個用戶端同時擷取,采用了加鎖機制提高了性能,下節我将分析伺服器端服務發現流程,下節見。

繼續閱讀