前言
Spring Cloud Eureka是Spring Cloud Netflix微服務套件中的一部分,主要負責實現微服務架構中的服務治理功能,包括服務注冊和服務發(fā)現。本文從源碼的角度,分析Eureka的服務治理機制。
Eureka服務治理機制
在Eureka服務治理架構中有三種角色,分別是:
角色一:服務注冊中心,Eureka提供的服務端,提供服務的注冊和發(fā)現功能:
角色二:服務提供者,提供服務的應用,需要將自己提供的服務注冊到Eureka,以供其他應用發(fā)現
角色三:服務消費者,消費者應用,從服務注冊中心獲取服務列表,從而知道從何處調用需要的服務
DiscoveryClient類
一般我們將Spring boot應用注冊到Eureka Server或者需要從Eureka Server中獲取服務列表時,需要做如下兩件事情:
1:在應用主類中配置@EnableDiscoveryClient注解:
2:在application.properties中用eureka.client.serviceUrl.defaultZone參數指定服務注冊中心地址
先從@EnableDiscoveryClient注解開始,看一下源碼:

從圖中紅框標注的注釋可以得知,此注解用來開啟DiscoveryClient的實例。搜索DiscoveryClient,可以發(fā)現一個類和一個接口,先來看一下類圖:?

從DiscoveryClient(com.netflix.discovery.DiscoveryClient)的類注釋中,我們可以知道,該類負責向Eureka Server注冊服務實例、向Eureka Server服務租約、當服務關閉時,向Eureka Server取消租約、查詢Eureka Server中的服務實例列表。
服務注冊
查看DiscoveryClient的構造方法,可以看到調用了如下方法:

可以看到,如果當前應用需要被注冊到Eureka中,則創(chuàng)建一個InstanceInfoReplicator類的實例,它會執(zhí)行一個定時任務,

該任務的具體執(zhí)行內容可以查看該類的run方法,

看到這里,我們應該能猜出來,注冊操作其實就是通過REST請求的方式進行的,傳入的參數為InstanceInfo對象,內部保存的就是關于服務的元數據。
服務獲取和服務續(xù)約
剛才的initScheduledTasks方法中還有兩個定時任務,分別是“服務獲取”和“服務續(xù)約”,

initScheduledTasks方法會啟動HeartbeatThread線程定時完成服務續(xù)約,默認續(xù)約的時間間隔為30秒,默認的服務信息保留時間為90秒,可以通過application.properties中啟動參數設置。
HeartbeatThread線程通過調用renew方法,直接以REST請求的方式實現服務續(xù)約。


再來看服務獲取邏輯,initScheduledTasks方法會啟動CacheRefreshThread線程定時完成服務獲取,默認的時間間隔為30秒,也可以通過application.properties中啟動參數設置。



可以看到服務獲取邏輯相對復雜一點,會根據是否是第一次獲取發(fā)起不同的REST請求和相應的處理,處理邏輯又分全量獲取和差量獲取。
服務注冊中心處理
通過上述分析,我們得知所有的交互都通過REST請求來發(fā)起的,那服務注冊中心又是如何處理這些請求的呢?Eureka Server對于各類REST請求的定義都位于com.netflix.eureka.resources包中,以處理服務注冊為例,

服務注冊的過程大致如下,先調用publishEvent方法,將該新服務注冊的事件傳播出去,再調用父類方法注冊實現,將InstanceInfo中的元數據保存在一個ConcurrentHashMap對象中。注冊中心存儲了兩層Map結構,第一層key為存儲的服務名稱,value為InstanceInfo中的appName屬性,第二層key為實例名稱,value為InstanceInfo中的instanceId屬性。
總結
本文從源碼的角度介紹了Spring Cloud Eureka的服務治理機制,但真正的服務治理機制絕非如此簡單,本文關注了其最重要的幾個方面,希望能對讀者有所幫助。