Spring Cloud Eureka原理分析(一):註冊過程-服務端

xinlmain發表於2019-02-28

Eureka的官方文件和Spring Cloud Eureka文件都有很多含糊的地方,其他資料也不多,只有讀讀原始碼維持生活這樣子……

本文將不會詳細介紹每個細節,而是講述一些關鍵的地方,便於查閱。

一些好的參考資料

Eureka-Server接受註冊請求

正常情況下會進入PeerAwareInstanceRegistryImpl#register(...)方法:

@Override
public void register(final InstanceInfo info, final boolean isReplication) {
   // 租約過期時間
   int leaseDuration = Lease.DEFAULT_DURATION_IN_SECS;
   if (info.getLeaseInfo() != null && info.getLeaseInfo().getDurationInSecs() > 0) {
       leaseDuration = info.getLeaseInfo().getDurationInSecs();
   }
   // 註冊應用例項資訊
   super.register(info, leaseDuration, isReplication);
   // Eureka-Server 複製
   replicateToPeers(Action.Register, info.getAppName(), info.getId(), info, null, isReplication);
}
複製程式碼

先呼叫父類 AbstractInstanceRegistry#register(...) 方法完成註冊,再將這個註冊資訊複製到同伴節點。

我們先來看註冊部分。

1 登錄檔registry的實際結構

registry在AbstractInstanceRegistry中宣告:

private final ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>> registry;
複製程式碼

它就是一個ConcurrentHashMap, 其Key為應用的AppID,Value為一個Map,其中的鍵值對為該應用的各個例項。(InstanceId為鍵,Lease<InstanceInfo>>為值)

Lease表示一個應用例項(Instance)的註冊期限,有租約到期和續租之說。InstanceInfo則表示一個例項的狀態,基本由客戶端(服務例項本身)提供。顯然,因為服務可能朝生夕死,網路環境千變萬化,需要知道服務的狀態,決定可不可用。

上一個圖,以對LeaseInstanceInfo有個初步印象:

Lease通過holder持有InstanceInfo

2 核心註冊過程

AbstractInstanceRegistry#register(...) 方法很長,這裡不全部貼出來,否則看得太累。只說一些重要的片段。其餘細節以後需要時補充。

  • 首先從registry中找到應用所對應的資料,記為gMap。如果沒有,說明之前沒有註冊過(或被刪除了),那就建立一個Map,加到registry中去。
// 以AppName作為應用的ID
Map<String, Lease<InstanceInfo>> gMap = registry.get(registrant.getAppName());
// 如果沒有,就建立並新增,略
複製程式碼
  • 在gMap中找此次註冊的例項對應的Lease。注意應用和例項之間的關係。 如果有,說明之前已經註冊成功過,需要使用其中的一些資訊,比如serviceUpTimestamp等。然後設定lease的registrationTimestamplastUpdateTimestamp為當前時間。
  • 經過一個OverriddenInstanceStatus計算,得出此應用例項當前的狀態。計算輸入包括registry中已有的該例項的lease的狀態,和此次註冊所宣告的狀態,以及服務端一系列rule來判斷。(同樣,這裡的細節如有必要以後再講)最終的InstanceStatus有如下幾種狀態:

Spring Cloud Eureka原理分析(一):註冊過程-服務端

  • 設定當前的InstanceInfo的lastUpdatedTimestamp
  • 如果是第一次註冊,設定lease的serviceUpTimestamp
  • recentlyChangedQueue中加一個包裝後的當前的lease,這個是幹啥的我們後面再講。
  • 呼叫invalidateCache(),傳入當前的應用名,例項的虛擬IP地址。這是幹啥的且聽下回。

3 複製註冊資訊到同伴節點過程

方式出人意料的簡單:依次呼叫同伴節點的register介面。

Over.

相關文章