大家好,我是悟空。
一、前言
注冊表對于注冊中心尤為重要,所有的功能都是圍繞這個注冊表展開。比如服務(wù) A 要想訪問服務(wù) B,就得知道服務(wù) B 的 IP 地址和端口號吧。如下圖所示,傳統(tǒng)的方式就是服務(wù) A 知道了服務(wù) B 的地址后,發(fā)送 HTTP 請求到對應(yīng)的 API 地址上。
那服務(wù) A 和 服務(wù) B 的信息其實就是放在注冊中心的注冊表里面的,由注冊中心統(tǒng)一管理所有服務(wù)的注冊、下線。服務(wù) A 和 服務(wù) B 想要獲取注冊信息,統(tǒng)一訪問注冊中心,拿到注冊表,就知道其他服務(wù)的 IP 地址 和端口號了。
上一講,我們講到一個 Eureka Client 成功注冊到 Eureka Server 后,Eureka Server 就會把注冊表信息存到一個 ConcurrentHashMap 中。
那 Client 怎么獲取其他客戶注冊信息呢?
二、首次獲取注冊信息
首先我們想一下,服務(wù) B 發(fā)送注冊請求到注冊中心了,那服務(wù) A 就得獲取注冊表了吧,服務(wù) A 本地一開始肯定是沒有注冊表信息的,那肯定就得到注冊中心把注冊表全部拉取一遍了。(這里服務(wù) A 也稱作 Eureka 客戶端)
服務(wù) A 對于注冊中心來說,就是
初次見面
,服務(wù) A 想把所有
注冊信息都在自己本地存一份,方便后續(xù)的 API 調(diào)用。
接下來我們從源碼角度分析下客戶端怎么獲取全量注冊表的吧。
客戶端發(fā)送獲取的請求
Client 初始化的時候,就會從 Eureka 注冊中心獲取全量的注冊表:
首次獲取注冊信息就是用在 DiscoveryClient 初始化的時候獲取的。我們可以從源碼中找到如下判斷:
if (clientConfig.shouldFetchRegistry() && !fetchRegistry(false)) { fetchRegistryFromBackup(); }
這段代碼的意思如圖所示:
就是先根據(jù)是否配置了 shouldFetchRegistry,如果配置了,則會調(diào)用 fetchRegistry 方法獲取注冊表。
因為是新的 client,所以肯定是沒有注冊信息的,所以本地的變量 applications = null。然后根據(jù)幾個條件來判斷是否需要全量獲取注冊表,滿足其中一個條件就會全量獲取:
- 條件一:是否強(qiáng)制全量獲取。傳的 false,不需要全量。
- 條件二:注冊表信息是否為空。application == null,為空,需要全量獲取。
- 條件三:獲取已注冊的 client 的個數(shù)是否等于 0。是的,需要全量獲取。
因為滿足 applications=null,所以需要全量獲取。
獲取全量注冊信息的方法:
getAndStoreFullRegistry()
在這個里面就會發(fā)送下面這個 HTTP 請求調(diào)用 jersey 的 restful 接口:
getApplications()
然后 Eureka Server 處理這個 http 的請求的類是在這里:ApplicationsResource 類的 getContainers 方法。這個方法里面就會去拿 Server 那邊注冊表了。
三、Server 端的注冊表緩存
Server 端會把注冊表放到緩存里面,讀取注冊表其實是從緩存里面讀取出來的。
分為兩級緩存,只讀緩存 readOnlyCacheMap
和讀寫緩存 readOnlyCacheMap
。
如下圖所示:
緩存的讀取邏輯如下:
Jersey Servlet 處理 HTTP 請求。
首先默認(rèn)會先從只讀緩存里面找。
- 沒有的話,再從讀寫緩存里面找。
- 找到了的話就更新只讀緩存,并返回找到的緩存。
- 還找不到的話,就返回空。
留幾個問題,放到緩存架構(gòu)那篇再講:
(1)兩級緩存數(shù)據(jù)怎么來的?
(2)緩存數(shù)據(jù)如何更新的?
(3)緩存如何過期?
然后,Eureka Client 獲取注冊表信息后,就會存到本地 localRegionApps 變量中。這樣 Client 就會有一份 Server 的注冊表信息了。
localRegionApps.set(this.filterAndShuffle(apps));
四、總結(jié)
注冊表無論是對于 Client 還是 Server 來說,都非常重要:
- 對于 Server 端來說,為了更好的提供查詢注冊表的服務(wù),使用了多級緩存來緩存注冊表信息。
- 對于 Client 端來說,首次獲取注冊表時就會全量抓取注冊表,存在自己本地。
后續(xù):第二次見面,怎么獲取注冊表呢?