Eureka參數詳解,緩存機制,及生產環境最佳配置

Eureka作爲spring cloud微服務架構裏的註冊中心,是非常核心的一個組件,它避免了複雜的選主算法,架構比較簡單,搭個demo也確實很快,但是如果要用於生產環境,還是得注意很多東西,尤其是下線延遲… 

 

服務獲取中的緩存問題

爲什麼修改client的默認心跳時間,會導致自我保護模式失效?

Eureka Service會認爲客戶端是以30s的頻率來發送心跳的。服務端期望收到的最大心跳時間是: 

n instances x 2(60s/30s) x threshold

如果是2個實例,Eureka會期望每分鐘有:2 instances x 2 x 85% =3.4個心跳,也就是說需要3個心跳。 

如果client的心跳改成15s,掛掉一個,另一個在1min內會發出4個心跳,而這時候的閾值還是3.4個,自我保護模式就失效了。 

核心原因就是在Eureka Server計算期望心跳數的時候寫死了每分鐘的心跳間隔,即30秒,所以他永遠會是*2(感覺像是新手寫的代碼啊啊啊 -_-)

 

 

還有一個參數可以調整,eureka.server.renewalThresholdUpdateIntervalMs,心跳閾值重新計算的週期,默認15分鐘,可以改短一點,2min

客戶端首次註冊時間爲什麼要30s?如何改進?

首次註冊行爲是和首次心跳綁定在一起的,首次心跳發送以後會收到not found的響應,client就知道還沒註冊過,client就會馬上註冊。首次心跳由參數 

eureka.instance.leaseRenewalIntervalInSeconds控制的,默認30

可以通過eureka.client.initialInstanceInfoReplicationIntervalSeconds參數來加快首次註冊的速度。他是控制首次改變實例狀態(UP/DOWN )的時間,啓動的時候狀態肯定是需要改變的,所以他可以用來加快首次註冊速度,並且改變這個值不會影響到保護模式

另外如果你使用的是spring cloud eureka的話沒首次註冊延遲的問題,他會馬上註冊

其他影響快速獲取服務信息的因素

【服務端緩存】 

因爲服務端默認會有個read only response cache(下面會細說),每30秒更新一次(eureka.server.response-cache-update-interval-ms),所以可能註冊了不是馬上能看到(雖然通過rest api不能看到,但是你可以在web ui上看到,因爲ui沒有緩存)

【客戶端緩存】 

Eureka Client緩存的定期更新週期,他由eureka.client.registryFetchIntervalSeconds控制,默認30秒, 改成5秒

【Ribbon緩存】 

如果你採用Ribbon來訪問服務,那麼這裏會有個緩存(他的數據來源是本地Eureka Client緩存),他由ribbon. ServerListRefreshInterval控制,默認30秒, 改成2秒

怎麼更快的踢掉沒有心跳的機器

eureka.instance.leaseExpirationDurationInSeconds,這個值用來控制多久踢掉機器,默認是3個心跳週期,有點久,可以考慮改成2個,他不會影響到保護模式(如果開啓自我保護模式,心跳間隔因爲上面的bug不能改,只能改這個了 -_-)

服務端緩存細節

Eureka內部的緩存分很多級,主要有registry、readWriterCacheMap、readOnlyCacheMap;另外還有一個維護最近180s增量的隊列recentlyChangedQueue

寫操作

包括註冊、取消註冊等,都直接操作在registry上,同時也會更新recentlyChangedQueue和readWriterCacheMap

讀操作

讀默認是從readOnlyCacheMap讀取,讀不到的話再從readWriterCacheMap,還沒有再從registry

濫用緩存的讀操作

這個讀操作的三級緩存結構,非常讓人困惑,registry已經是ConcurrentHashMap,純內存操作,性能非常高了,爲什麼前面還要加兩級緩存;readWriterCacheMap的數據是在寫入以後responseCacheAutoExpirationInSeconds(默認180)秒內失效,readOnlyCacheMap則是一個定時任務,每responseCacheUpdateIntervalMs(默認30)秒從readWriterCacheMap獲取最新數據

去掉readOnlyCacheMap

從CAP理論上看,Eureka是一個AP系統,但是在C層面這麼弱,就是因爲各種無謂的緩存造成的,看了下readWriterCacheMap去掉比較難,但是readOnlyCacheMap有一個開關useReadOnlyResponseCache,果斷關掉!!

Time Lag

最後再來看下Eureka wiki中提到的2min time lag問題,其實分多個角度看,不一定是2min

服務正常上線/修改,最大可能會有120s滯後

- 30(首次註冊 init registe) + 30(readOnlyCacheMap)+30(client fetch interval)+30(ribbon)=120- 如果是在Spring Cloud環境下使用這些組件(Eureka, Ribbon),不會有首次註冊30秒延遲的問題,服務啓動後會馬上註冊,所以從註冊到發現,最多可能是90s。

服務異常下線:最大可能會有270s滯後

- 定時清理任務每eureka.server. evictionIntervalTimerInMs(默認60)執行一次清理任務- 每次清理任務會把90秒(3個心跳週期,eureka.instance.leaseExpirationDurationInSeconds)沒收到心跳的踢除,但是根據官方的說法 ,因爲代碼實現的bug,這個時間其實是兩倍,即180秒,也就是說如果一個客戶端因爲網絡問題或者主機問題異常下線,可能會在180秒後才剔除- 讀取端,因爲readOnlyCacheMap以及客戶端緩存的存在,可能會在30(readOnlyCacheMap)+30(client fetch interval)+30(ribbon)=90- 所以極端情況最終可能會是180+90=270

生產環境最佳配置

總結前面3點,經過梳理後,推薦的生產環境最佳配置如下:(可用於中小規模環境):

Eureka Server端配置

## 中小規模下,自我保護模式坑比好處多,所以關閉它

eureka.server.enableSelfPreservation=false

## 心跳閾值計算週期,如果開啓自我保護模式,可以改一下這個配置

## eureka.server.renewalThresholdUpdateIntervalMs=120000

 

## 主動失效檢測間隔,配置成5秒

eureka.server.evictionIntervalTimerInMs=5000

 

## 心跳間隔,5秒

eureka.instance.leaseRenewalIntervalInSeconds=5

## 沒有心跳的淘汰時間,10秒

eureka.instance.leaseExpirationDurationInSeconds=10

 

## 禁用readOnlyCacheMap

eureka.server. useReadOnlyResponseCache=false

服務提供者和clinet配置

## 心跳間隔,5秒eureka.instance.leaseRenewalIntervalInSeconds=5## 沒有心跳的淘汰時間,10秒eureka.instance.leaseExpirationDurationInSeconds=10# 定時刷新本地緩存時間eureka.client.registryFetchIntervalSeconds=5# ribbon緩存時間ribbon.ServerListRefreshInterval=2000

改成上面配置後:

  • 正常上線下線客戶端最大感知時間:eureka.client.registryFetchIntervalSeconds+ribbon. ServerListRefreshInterval = 7秒
  • 異常下線客戶端最大感知時間: 

2*eureka.instance.leaseExpirationDurationInSeconds+ 

eureka.server.evictionIntervalTimerInMs+ 

eureka.client.registryFetchIntervalSeconds+ 

ribbon. ServerListRefreshInterval = 32

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章