Eureka詳解系列(五)–Eureka Server部分的源碼和配置
簡介
按照原定的計劃,我將分三個部分來分析 Eureka 的源碼:
- Eureka 的配置體系(已經寫完,見Eureka詳解系列(三)–探索Eureka強大的配置體系);
- Eureka Client 的交互行為(已經寫完,見Eureka詳解系列(四)–Eureka Client部分的源碼和配置 );
- Eureka Server 的交互行為。
今天,我們來研究第三部分的源碼。
分析的思路和第二部分的一樣,先明確 Eureka Server 需要具備哪些功能,再從源碼層面分析如何實現這些功能,最後補充 Eureka Server 的配置解讀。
項目環境
os:win 10
jdk:1.8.0_231
eureka:1.10.11
tomcat:9.0.21
Eureka Server 的功能
還是來回顧 Eureka 的整個交互過程。
首先,Eureka Server 需要和 Eureka Client 交互,所以它需要能夠處理 Eureka Client 的各種請求,這些請求包括:
- 獲取註冊表(Application Client 的請求);
- 註冊、續約、註銷實例(Application Service 的請求);
除此之外,在集群中,它需要和對等節點交互,交互內容主要包括:
- 將自己的註冊表變更操作同步到其他節點;
- 處理其他節點同步註冊表的請求。
其實,一個完整的 Eureka Server 項目本身也包含了 Eureka Client 的部分,也就是說,它可以註冊自己和消費包括自己在內的服務,可以在 eureka-client.properties 增加以下配置來關閉掉這兩個部分的功能(不建議這麼做):
# 當前實例是否註冊到Eureka Server。默認true
eureka.registration.enabled=false
# 當前實例是否需要從Eureka Server獲取服務註冊表
eureka.shouldFetchRegistry=false
如何實現這些功能
知道了 Eureka Server 需要具備哪些功能,接下來我們就從源碼的角度來看看怎樣實現這些功能。
和之前一樣,我更多的會從設計的層面來分析,而不會順序地去看每個過程的程式碼,即重設計、輕實現。
那麼,還是從一個 UML 圖開始吧。有了它,相信大家看源碼時會更輕鬆一些。
AbstractInstanceRegistry
里放了一張註冊表,用來存放所有的實例對象,通過它可以處理 Eureka Client 或者其他 Eureka Server 的請求,包括註冊、續約、註銷實例以及獲取註冊表等。
它的子類PeerAwareInstanceRegistryImpl
提供了多節點的支援,這裡以續約實例的方法為例,相同的操作還會被同步到其他節點(對等節點的請求除外)。
public boolean renew(final String appName, final String id, final boolean isReplication) {
// 先調用父類AbstractInstanceRegistry的方法
if (super.renew(appName, id, isReplication)) {
// 再將操作同步到其他節點,最終是調用PeerEurekaNode的方法進行同步
replicateToPeers(Action.Heartbeat, appName, id, null, null, isReplication);
return true;
}
return false;
}
除此之外,PeerAwareInstanceRegistryImpl
還啟動了三個定時任務:
- 更新
PeerEurekaNode
列表。例如,當我們使用 DNS 配合 serviceUrl 時,對等節點的地址可能會變化,所以需要及時更新。這個定時任務用於支援集群的故障轉移和擴容。 - 更新參數 numberOfRenewsPerMinThreshold–每分鐘至少要有多少實例續約。當每分鐘續約實例少於這個值時(eureka 認為是災難性的網路故障導致的),Eureka Server 將進入自我保護模式,此時,它不會再主動淘汰實例,直到我們主動關閉該模式,或者續約實例達到了閾值。我們一般可以通過以下參數來控制。而每分鐘至少要有多少實例續約,這個數值受到實例總數的影響,所以需要定時更新。
# 期望實例多久續約一次
eureka.expectedClientRenewalIntervalSeconds=30
# 續約實例的閾值,未達到將開啟自我保護模式
eureka.renewalPercentThreshold=0.85
# 是否啟用保護模式
eureka.enableSelfPreservation=true
- 丟棄未能及時續約的實例。默認情況下,實例超過 90s 未能續約的話,Eureka Server 會將其丟棄掉。
從哪裡開始看源碼
Eureka Server 是作為一個 Web 應用運行的,要看源碼比較難找到入口。打開Eureka詳解系列(二)–如何使用Eureka(原生API,無Spring) 例子里的 web.xml,可以看到配置了一個監聽器,這個類就是 Eureka Server 初始化的入口。
<listener>
<listener-class>com.netflix.eureka.EurekaBootStrap</listener-class>
</listener>
在這個類裡面,我們主要關注這一段程式碼(程式碼有刪減)。
protected void initEurekaServerContext() throws Exception {
// 下面這一段是為了初始化Eureka Client所需要的對象,上一篇部落格講過了
EurekaInstanceConfig instanceConfig = new MyDataCenterInstanceConfig();
ApplicationInfoManager applicationInfoManager = new ApplicationInfoManager(
instanceConfig, new EurekaConfigBasedInstanceInfoProvider(instanceConfig).get());
EurekaClientConfig eurekaClientConfig = new DefaultEurekaClientConfig();
eurekaClient = new DiscoveryClient(applicationInfoManager, eurekaClientConfig);
// 載入eureka-server.properties的配置
EurekaServerConfig eurekaServerConfig = new DefaultEurekaServerConfig();
ServerCodecs serverCodecs = new DefaultServerCodecs(eurekaServerConfig);
// 初始化註冊表對象(支援多節點)
PeerAwareInstanceRegistry registry = new PeerAwareInstanceRegistryImpl(
eurekaServerConfig,
eurekaClient.getEurekaClientConfig(),
serverCodecs,
eurekaClient
);
// 初始化PeerEurekaNodes對象
PeerEurekaNodes peerEurekaNodes = getPeerEurekaNodes(
registry,
eurekaServerConfig,
eurekaClient.getEurekaClientConfig(),
serverCodecs,
applicationInfoManager
);
// 1. 初始化PeerEurekaNode列表,
// 2. 啟動定時任務:更新PeerEurekaNode列表
peerEurekaNodes.start();
// 1. 將PeerEurekaNode列表的指針給到PeerEurekaNodes對象對象
// 2. 啟動定時任務:更新參數numberOfRenewsPerMinThreshold--每分鐘至少要有多少實例續約,它是判斷是否開啟自我保護模式的依據
registry.init(peerEurekaNodes);
// 從其他節點獲取實例列表並註冊到本地的註冊表
int registryCount = registry.syncUp();
// 1. 初始化參數numberOfRenewsPerMinThreshold--每分鐘要求多少實例續約
// 2. 開啟定時任務:淘汰未能正常續約的實例
registry.openForTraffic(applicationInfoManager, registryCount);
}
完成初始化後,Eureka Server 就可以處理 Eureka Client 的請求了。因為 Eureka Server 使用 jersey 作 Web 框架(jersey 和 struts2、springMVC 作用差不多,沒接觸過也不礙事),所以,只要找到添加了javax.ws.rs.Path
註解的類,就能找到這部分程式碼的入口。
Eureka Server 的配置解讀
回顧下Eureka詳解系列(三)–探索Eureka強大的配置體系的內容,在 Eureka 里,配置分成了三種:
- EurekaInstanceConfig:當前實例身份的配置資訊,即我是誰?
- EurekaServerConfig:一些影響當前Eureka Server和客戶端或對等節點交互行為的配置資訊,即怎麼交互?
- EurekaClientConfig:一些影響當前實例和Eureka Server交互行為的配置資訊,即和誰交互?怎麼交互?
這裡我們來講講EurekaServerConfig
的配置參數,對應的是 eureka-server.properties 里的配置。
# 期望實例多久續約一次
eureka.expectedClientRenewalIntervalSeconds=30
# 續約實例的閾值,未達到將開啟自我保護模式
eureka.renewalPercentThreshold=0.85
# 是否啟用保護模式
eureka.enableSelfPreservation=true
# 更新參數numberOfRenewsPerMinThreshold的定時任務多久執行一次
renewalThresholdUpdateIntervalM=900000
# 更新PeerEurekaNode列表的定時任務多久執行一次
peerEurekaNodesUpdateIntervalMs=600000
# 淘汰未能正常續約實例的定時任務多久執行一次
evictionIntervalTimerInMs=60000
# 這幾個一般不用,我就不展開了。有需要的話可以
#awsAccessId=
#awsSecretKey=
eipBindRebindRetries=3
eipBindRebindRetryIntervalMsWhenUnbound=60000
eipBindRebindRetryIntervalMs=300000
waitTimeInMsWhenSyncEmpty=300000
shouldBatchReplication=false
disableDelta=false
numberRegistrySyncRetries=5
registrySyncRetryWaitMs=30000
enableReplicatedRequestCompression=false
minAvailableInstancesForPeerReplication=-1
peerEurekaStatusRefreshTimeIntervalMs=30000
peerNodeConnectTimeoutMs=1000
peerNodeReadTimeoutMs=5000
peerNodeTotalConnections=1000
peerNodeTotalConnectionsPerHost=500
numberOfReplicationRetries=5
maxElementsInPeerReplicationPool=10000
maxIdleThreadAgeInMinutesForPeerReplication=15
minThreadsForPeerReplication=5
maxThreadsForPeerReplication=20
maxTimeForReplication=30000
primeAwsReplicaConnections=true
maxIdleThreadAgeInMinutesForStatusReplication=10
minThreadsForStatusReplication=1
maxThreadsForStatusReplication=1
maxElementsInStatusReplicationPool=10000
disableDeltaForRemoteRegions=false
remoteRegionConnectTimeoutMs=2000
remoteRegionReadTimeoutMs=5000
remoteRegionTotalConnections=1000
remoteRegionTotalConnectionsPerHost=500
remoteRegionConnectionIdleTimeoutSeconds=30
remoteRegion.gzipContent=true
#remoteRegionUrlsWithName=
#remoteRegion.appWhiteList=
remoteRegion.registryFetchIntervalInSeconds=30
remoteRegion.fetchThreadPoolSize=20
#remoteRegion.trustStoreFileName=
remoteRegion.trustStorePassword=changeit
remoteRegion.disable.transparent.fallback=false
shouldUseAwsAsgApi=true
asgQueryTimeoutMs=300
asgUpdateIntervalMs=300000
asgCacheExpiryTimeoutMs=600000
retentionTimeInMSInDeltaQueue=180000
deltaRetentionTimerIntervalInMs=30000
responseCacheAutoExpirationInSeconds=180
responseCacheUpdateIntervalMs=30000
shouldUseReadOnlyResponseCache=true
syncWhenTimestampDiffers=true
auth.shouldLogIdentityHeaders=true
route53BindRebindRetries=3
route53BindRebindRetryIntervalMs=300000
route53DomainTTL=30
initialCapacityOfResponseCache=1000
jsonCodecName=com.netflix.discovery.converters.wrappers.CodecWrappers.LegacyJacksonJson
xmlCodecName=com.netflix.discovery.converters.wrappers.CodecWrappers.XStreamXml
以上比較宏觀地講完了 Eureka Server 的源碼和配置,具體的細節歡迎私信交流。
最後,感謝您的閱讀。
參考資料
//github.com/Netflix/eureka/wiki/Eureka-at-a-glance
本文為原創文章,轉載請附上原文出處鏈接://www.cnblogs.com/ZhangZiSheng001/p/14395079.html