天天看點

spring cloud eureka部分源碼分析及微服務管理功能

eureka原生的管理頁面隻有檢視服務節點和一些資訊,沒有動态啟用停用服務節點的功能

一. EurekaClient擷取所有注冊的服務

eureka用戶端會加載一個定時任務去擷取注冊中心的服務,任務的配置在:com.netflix.discovery.DiscoveryClient,重新整理的線程是:CacheRefreshThread。

擷取的注冊中心服務的時候,會把所有服務都拉取下來,但是預設會過濾掉狀态不是UP的服務。

擷取服務的具體代碼在:DiscoveryClient.getAndStoreFullRegistry()方法

過濾服務狀态的代碼在:DiscoveryClient.filterAndShuffle()方法

由此可以看出,是否需要過濾服務狀态的配置是在clientConfig中,下一步尋找這個配置具體要怎麼寫。在類中可以看出,clientConfig對應的是EurekaClientConfig,但這是個接口,有兩個實作

EurekaClientConfig

DefaultEurekaClientConfig

EurekaClientConfigBean

僅看名字以為是使用的DefaultEurekaClientConfig,找到對應的配置方法是:

于是找到namespace以及對應的常量,組合起來的配置應該是:eureka.shouldFilterOnlyUpInstances,然而,加上配置後并沒有什麼用。仔細看看這是eureka包裡的,而不是spring包裡的,是以這應該是獨立使用eureka的時候配置的方法,回過頭來看,另外一個配置的實作(EurekaClientConfigBean)是spring cloud包裡的,找找在哪裡有用到?果然不出所料,在EurekaClientAutoConfiguration自動配置中有初始化此bean,并且EurekaClientConfigBean上有@ConfigurationProperties注解,其實也就是個properties。是以結論出來了,EurekaClientConfigBean實際是将properties配置和對EurekaClientConfig接口的實作放一起了。。。,這樣就能找到配置不自動過濾狀态為UP的服務的方法了

二. 動态更新EurekaClient的狀态

首先,spring cloud官方文檔中,介紹了一個endpoint(/service-registry/instance-status),提供了get和post方法,get方法用來擷取節點狀态,post用來修改節點狀态

Service Registry Actuator Endpoint

A /service-registry actuator endpoint is provided by Commons. This endpoint relys on a Registration bean in the Spring Application Context. Calling /service-registry/instance-status via a GET will return the status of the Registration. A POST to the same endpoint with a String body will change the status of the current Registration to the new value. Please see the documentation of the ServiceRegistry implementation you are using for the allowed values for updating the status and the values retured for the status.

spring cloud eureka client預設是沒有開啟endpoint的,需要自己引入依賴

不過,引入依賴後會不止這一個endpoint,并且需要安全認證,當然也可以配置不需要安全認證:

為了不依賴actutator包,并且了解spring cloud具體是如何更新節點狀态的,找到了endpoint中修改狀态的具體實作:ServiceRegistryEndpoint。可以看出,主要是通過ServiceRegistry和Registration實作的,而這兩個接口并不是actuator包裡的,是以嘗試自己實(拷)現(貝)一下。自己寫一個controller,注入以上兩個對象,然後将ServiceRegistryEndpoint中的擷取和修改狀态的方法複制粘貼,源碼如下:

需要注意的是

ServiceRegistry有Registration接口的實作類的泛型,如果不對應會注入失敗,這樣看具體是哪個實作類?ServiceRegistry隻有一個實作類:EurekaServiceRegistry,是以結果就顯而易見了

當然,這兩個bean的初始化也會在自動配置類中(EurekaClientAutoConfiguration)

三. 動态管理spring cloud eureka服務

基于以上兩點,就可以動态停用或啟用eureka中注冊的服務節點了。建立一個獨立的web應用,與普通的服務一樣注冊到eureka中心,當然為了還是需要與其他服務有些不一樣的配置

然後就可以使用EurekaClient擷取注冊中心的服務了

如果需要動态修改節點的狀态,以達到停用和啟用服務節點的目的,可以使用http調用對應節點的接口

當然如果是使用服務節點的actuator endpoint接口,調用接口的位址不一樣(還有安全認證,此處代碼未涉及),需要注意的是,endpoint接收的參數是@RequestBody(并且使用的jackson轉換,fastjson轉換是會出現異常的)

由于eureka注冊中心沒有通知的功能,隻能由節點自己發起重新整理請求,是以修改狀态後,需要等到相關節點下一次重新整理後才會生效。節點重新整理是通過定時任務實作的,源碼在com.netflix.discovery.DiscoveryClient中,并且任務是在構造方法中初始化的,還不能自己手動觸發,主要代碼如下:

配置在EurekaClientAutoConfiguration-->RefreshableEurekaClientConfiguration,使用DiscoveryClient的子類CloudEurekaClient執行個體化

CloudEurekaClient中有一個重新整理的方法,釋出一個心跳事件,但這個方法是protected,沒法通過執行個體調用,并且依賴于心跳事件。應用節點預設重新整理事件是60秒一次,時間也不算太長,是以動态停用節點後再60秒内生效,應該是在能接受的範圍吧,并且這個時間還能配置