1. 程式人生 > >Eureka詳解系列(五)--Eureka Server部分的原始碼和配置

Eureka詳解系列(五)--Eureka Server部分的原始碼和配置

# 簡介 按照原定的計劃,我將分三個部分來分析 Eureka 的原始碼: 1. Eureka 的配置體系(已經寫完,見[Eureka詳解系列(三)--探索Eureka強大的配置體系](https://www.cnblogs.com/ZhangZiSheng001/p/14374005.html)); 2. Eureka Client 的互動行為(已經寫完,見[Eureka詳解系列(四)--Eureka Client部分的原始碼和配置](https://www.cnblogs.com/ZhangZiSheng001/p/14381169.html) ); 3. 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 的各種請求,這些請求包括: 1. **獲取登錄檔**(Application Client 的請求); 2. **註冊、續約、登出例項**(Application Service 的請求); 除此之外,在叢集中,它需要和對等節點互動,互動內容主要包括: 2. **將自己的登錄檔變更操作同步到其他節點**; 3. **處理其他節點同步登錄檔的請求**。 其實,一個完整的 Eureka Server 專案本身也包含了 Eureka Client 的部分,也就是說,它可以註冊自己和消費包括自己在內的服務,可以在 eureka-client.properties 增加以下配置來關閉掉這兩個部分的功能(不建議這麼做): ```properties # 當前例項是否註冊到Eureka Server。預設true eureka.registration.enabled=false # 當前例項是否需要從Eureka Server獲取服務登錄檔 eureka.shouldFetchRegistry=false ``` # 如何實現這些功能 知道了 Eureka Server 需要具備哪些功能,接下來我們就從原始碼的角度來看看怎樣實現這些功能。 和之前一樣,我更多的會從設計的層面來分析,而不會順序地去看每個過程的程式碼,即重設計、輕實現。 那麼,還是從一個 UML 圖開始吧。有了它,相信大家看原始碼時會更輕鬆一些。
`AbstractInstanceRegistry`裡放了一張登錄檔,用來存放所有的例項物件,通過它可以處理 Eureka Client 或者其他 Eureka Server 的請求,包括註冊、續約、登出例項以及獲取登錄檔等。 它的子類`PeerAwareInstanceRegistryImpl`提供了多節點的支援,這裡以續約例項的方法為例,相同的操作還會被同步到其他節點(對等節點的請求除外)。 ```java 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`還啟動了三個定時任務: 1. **更新`PeerEurekaNode`列表**。例如,當我們使用 DNS 配合 serviceUrl 時,對等節點的地址可能會變化,所以需要及時更新。這個定時任務用於支援叢集的故障轉移和擴容。 2. **更新引數 numberOfRenewsPerMinThreshold--每分鐘至少要有多少例項續約**。當每分鐘續約例項少於這個值時(eureka 認為是災難性的網路故障導致的),Eureka Server 將進入自我保護模式,此時,它不會再主動淘汰例項,直到我們主動關閉該模式,或者續約例項達到了閾值。我們一般可以通過以下引數來控制。而每分鐘至少要有多少例項續約,這個數值受到例項總數的影響,所以需要定時更新。 ```properties # 期望例項多久續約一次 eureka.expectedClientRenewalIntervalSeconds=30 # 續約例項的閾值,未達到將開啟自我保護模式 eureka.renewalPercentThreshold=0.85 # 是否啟用保護模式 eureka.enableSelfPreservation=true ``` 3. **丟棄未能及時續約的例項**。預設情況下,例項超過 90s 未能續約的話,Eureka Server 會將其丟棄掉。 # 從哪裡開始看原始碼 Eureka Server 是作為一個 Web 應用執行的,要看原始碼比較難找到入口。開啟[Eureka詳解系列(二)--如何使用Eureka(原生API,無Spring)](https://www.cnblogs.com/ZhangZiSheng001/p/14337985.html) 例子裡的 web.xml,可以看到配置了一個監聽器,這個類就是 Eureka Server 初始化的入口。 ```xml com.netflix.eureka.EurekaBootStrap
``` 在這個類裡面,我們主要關注這一段程式碼(程式碼有刪減)。 ```java 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強大的配置體系](https://www.cnblogs.com/ZhangZiSheng001/p/14374005.html)的內容,在 Eureka 裡,配置分成了三種: 1. **EurekaInstanceConfig**:當前例項身份的配置資訊,即**我是誰?** 2. **EurekaServerConfig**:一些影響當前Eureka Server和客戶端或對等節點互動行為的配置資訊,即**怎麼互動?** 3. **EurekaClientConfig**:一些影響當前例項和Eureka Server互動行為的配置資訊,即**和誰互動?怎麼互動?** 這裡我們來講講`EurekaServerConfig`的配置引數,對應的是 eureka-server.properties 裡的配置。 ```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 的原始碼和配置,具體的細節歡迎私信交流。 最後,感謝您的閱讀。 # 參考資料 https://github.com/Netflix/eureka/wiki/Eureka-at-a-glance >
相關原始碼請移步:[https://github.com/ZhangZiSheng001/eureka-demo](https://github.com/ZhangZiSheng001/eureka-demo) >本文為原創文章,轉載請附上原文出處連結:[https://www.cnblogs.com/ZhangZiSheng001/p/14395079.html](https://www.cnblogs.com/ZhangZiSheng001/p/14395079