服務端快取
服務端的註冊資訊讀取使用快取,而非直接讀取registry那個ConcurrentHashMap
。快取的主要邏輯都在ResponseCacheImpl
這個類中。
快取有兩層,第一層是Guava的帶生存時間的LoadingCache
,稱為readWriteCacheMap
;第二層是一個ConcurrentHashMap
,稱為readOnlyCacheMap
。
參見下面的示意圖:
下面看一下圖中兩個重要的方法。
generatePayload(Key key)
此方法接受一個Key
型別的引數,返回一個Value
型別。
其中Key
中重要的欄位有:
KeyType
,表示payload文字格式,有JSON和XML兩種值。EntityType
,表示快取的型別,有Application
,VIP
,SVIP
三種值。entityName
,表示快取的名稱,可能是單個應用名,也可能是ALL_APPS
或ALL_APPS_DELTA
。
Value
則有一個String
型別的payload和一個byte
陣列,表示gzip壓縮後的位元組。
generatePayload()
中根據EntityType
和EntityName
,會呼叫不同的方法獲取regitry中的資訊。
registry.getApplications()
: 得到所有的應用註冊資訊,結果為Applications
物件。registry.getApplicationsDeltas()
:得到增量更新資訊。registry.getApplication()
:得到單個應用資訊。getApplicationsForVip
:就是先得到所有的應用註冊資訊,然後提取出vipAddress
符合請求的應用資訊。
vip和svip是什麼
在Spring Cloud Eureka中,這兩個設定變成了VirtualHostName和SecureVirtualHostName,應該是類似DNS名稱。
invalidate(String appName, ...)
傳入的為某個應用名,而實際上要讓以下快取失效:
- 應用的快取
- ALL_APPS快取
- ALL_APPS_DELTA快取
定時重新整理readOnlyCache任務
行為很簡單,就是把readWriteMap拷貝到readOnlyMap(但只拷貝readOnlyCache中已有的key)。
任務執行頻率由eureka.server.responseCacheUpdateIntervalMs
控制,預設為30秒。
另外,eureka.server.useReadOnlyResponseCache
可以設定是否啟用readOnlyCache,預設啟用。
全量資訊與增量資訊
前文已述,generatePayload()
方法根據entityName
是ALL_APPS
或ALL_APPS_DELTA
決定生成已註冊的全量資訊,還是增量資訊。
全量資訊
呼叫registry.getApplications()
,最終就是從本地(也可能包含遠端)的registry中讀取所有註冊資訊,構造成Applications
物件。
增量資訊
在前兩篇文章中,提到了registry的實現類有一個AbstractInstanceRegistry.recentlyChangedQueue
佇列,儲存最近的租約變更記錄。在註冊、下線等操作時,會修改此佇列。
另外,還有一個定時任務專門對超過一定時長的記錄進行移除。定時任務的執行間隔由eureka.server.deltaRetentionTimerIntervalInMs
控制;時長閾值由eureka.server.retentionTimeInMSInDeltaQueue
控制。
客戶端獲取增量資訊,與本地快取合併後通服務端的全量資訊比較雜湊值(雜湊演算法有特別實現,主要根據註冊應用內容)。如果雜湊值不同,則增量獲取失敗,需要一次全量獲取。