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
則表示一個例項的狀態,基本由客戶端(服務例項本身)提供。顯然,因為服務可能朝生夕死,網路環境千變萬化,需要知道服務的狀態,決定可不可用。
上一個圖,以對Lease
和InstanceInfo
有個初步印象:
2 核心註冊過程
AbstractInstanceRegistry#register(...)
方法很長,這裡不全部貼出來,否則看得太累。只說一些重要的片段。其餘細節以後需要時補充。
- 首先從registry中找到應用所對應的資料,記為gMap。如果沒有,說明之前沒有註冊過(或被刪除了),那就建立一個Map,加到registry中去。
// 以AppName作為應用的ID
Map<String, Lease<InstanceInfo>> gMap = registry.get(registrant.getAppName());
// 如果沒有,就建立並新增,略
複製程式碼
- 在gMap中找此次註冊的例項對應的Lease。注意應用和例項之間的關係。 如果有,說明之前已經註冊成功過,需要使用其中的一些資訊,比如
serviceUpTimestamp
等。然後設定lease的registrationTimestamp
和lastUpdateTimestamp
為當前時間。 - 經過一個OverriddenInstanceStatus計算,得出此應用例項當前的狀態。計算輸入包括registry中已有的該例項的lease的狀態,和此次註冊所宣告的狀態,以及服務端一系列rule來判斷。(同樣,這裡的細節如有必要以後再講)最終的InstanceStatus有如下幾種狀態:
- 設定當前的InstanceInfo的
lastUpdatedTimestamp
- 如果是第一次註冊,設定lease的
serviceUpTimestamp
。 - 往
recentlyChangedQueue
中加一個包裝後的當前的lease,這個是幹啥的我們後面再講。 - 呼叫
invalidateCache()
,傳入當前的應用名,例項的虛擬IP地址。這是幹啥的且聽下回。
3 複製註冊資訊到同伴節點過程
方式出人意料的簡單:依次呼叫同伴節點的register介面。
Over.