Eureka是什麼?
Eureka是基于REST(Representational State Transfer)服務,主要以AWS雲服務為支撐,提供服務發現并實作負載均衡和故障轉移。我們稱此服務為Eureka服務。Eureka提供了Java用戶端元件,Eureka Client,友善與服務端的互動。用戶端内置了基于round-robin實作的簡單負載均衡。在Netflix,為Eureka提供更為複雜的負載均衡方案進行封裝,以實作高可用,它包括基于流量、資源使用率以及請求傳回狀态的權重負載均衡。
Eureka架構
Eureka架構從CAP理論看,Eureka是一個AP系統,優先保證可用性(A)和分區容錯性(P),Eureka裡使用了大量的緩存。
Eureka中的一些概念
Register :服務注冊
Eureka用戶端向Eureka Server注冊時,它提供自身的中繼資料,比如IP位址、端口等
Renew:服務續約
Eureka用戶端會每隔30秒發送一次心跳來續約。通過續約來告知Eureka Server該用戶端仍然存在。
Fetch Registries:擷取注冊清單資訊
Eureka用戶端從伺服器擷取系統資料庫資訊,将其緩存到本地。用戶端會使用該資訊查找其他服務,進而進行遠端調用。該注冊清單資訊定期(每30秒)更新一次。
Cancel:服務下線
Eureka用戶端在程式關閉時向Eureka伺服器發送取消請求。
Eviction:服務剔除
在預設情況下,當Eureka用戶端90秒沒有向Eureka伺服器發送續約,Eureka伺服器就會将該服務執行個體從服務注冊清單删除。
除了以上的特性外,Eureka的緩存機制也非常經典,下面詳細介紹一下。
Eureka Server裡存在三個變量(registry、readWriteCacheMap、readOnlyCacheMap)儲存服務注冊資訊。
Eureka用戶端向服務端注冊之後,資料會立即同步到readWriteCacheMap和registry。
Eureka用戶端想檢視注冊資訊,每隔30秒從readOnlyCacheMap拉取。
readOnlyCacheMap會通過定時器每30秒從readWriteCacheMap拉取。
還有一個線程每隔60會将90秒都沒有續約的服務剔除出去。
變量
類型
說明
registry
ConcurrentHashMap
實時更新,類AbstractInstanceRegistry成員變量,UI端請求的是這裡的服務注冊資訊
readWriteCacheMap
Guava Cache
實時更新,類ResponseCacheImpl成員變量,緩存時間180秒
readOnlyCacheMap
周期更新,類ResponseCacheImpl成員變量,預設每30s從readWriteCacheMap更新,Eureka client預設從這裡更新服務注冊資訊,可配置直接從readWriteCacheMap更新
本文使用的是2.0.2.RELEASE版本
接下來開始分析Eureka Client的源碼。引入spring-cloud-starter-netflix-eureka-client後,Eureka Client會自動啟用。EurekaClientAutoConfiguration配置類生效,會注入Bean CloudEurekaClient,然後調用父類DiscoveryClient的構造方法。
接下來看initScheduledTasks方法
再來細看上面3個主要方法的具體邏輯。
1. 緩存重新整理
然後調用EurekaHttpClient接口的方法去擷取服務清單。請求發送通過jersey
2. 服務心跳
繼續跟蹤HeartbeatThread方法
3. 服務注冊
跟蹤instanceInfoReplicator.start方法
4. 服務關閉
服務關閉之後,會回調到EurekaAutoServiceRegistration類的stop方法,回調的方法是:
SmartLifecycle接口也有這個作用,不過我本地使用了一下,是通過ContextClosedEvent來回調的。
從上文分析得知Eureka Client調取服務端的接口都是通過EurekaHttpClient接口,而最終發送請求的httpClient是jersey裡面的ApacheHttpClient4。
Eureka Server需要做的事有:
維護服務注冊資訊清單
接收用戶端的register、renew、cancel等請求
Eureka Server多節點之間的資料複制同步
項目啟動時,EurekaServerAutoConfiguration會被自動注入到容器中。
1. 請求接受處理
InstanceResource類主要用于接受請求,收到請求後調用InstanceRegistry類的方法進行處理。以renew為例:
2. 服務剔除
EurekaServerAutoConfiguration類引入了EurekaServerInitializerConfiguration類。容器初始化會觸發start方法,start方法如下:
postInit代碼如下:
3. readOnlyCacheMap緩存周期更新
DefaultEurekaServerContext類的initialize方法上加了@PostConstruct注解,會在bean構造後被執行:
init()-》 initializedResponseCache()-》new ResponseCacheImpl
ResponseCacheImpl方法如下:
番外:源碼裡有一個這個東西,存最近的資料,如果有相同需求可以借鑒
書山有路勤為徑,學海無涯苦作舟