Eureka服務註冊中心搭建好後頁面有個錯誤信息怎麼辦?
這篇博文總結下當使用Eureka 服務註冊中心時頁面可能出現的兩個錯誤提示信息。
1.1 問題背景
當使用Eureka 搭建好服務註冊中心的時候,頁面百分之九十九可能會看到這個錯誤提示:
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY’RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.
翻譯成中文就是:
緊急! 如果不是,EUREKA可能會不正確地提出索賠要求。 續訂比閾值要少,因此僅出於安全性考慮,實例不會過期。
有人說,在Eureka Server 服務註冊中心的配置文件中將這個屬性設置成false 就行了。
# 默認值是true
eureka.server.enable-self-preservation=false
但是當你修改成false 後會發現那個錯誤信息是消失了,但是卻變成了這個新的錯誤信息
THE SELF PRESERVATION MODE IS TURNED OFF. THIS MAY NOT PROTECT INSTANCE EXPIRY IN CASE OF NETWORK/OTHER PROBLEMS.
翻譯成中文就是:
自我保護模式已關閉。 在網絡/其他問題的情況下,這可能無法保護實例到期。
這到底是什麼意思呢?
1.2 問題分析整理
eureka.server.enable-self-preservation
解決上面問題的關鍵在於理解這個自我保護機制是什麼意思?
- 確保您已訪問此頁面以瞭解有關Eureka羣集配置的信息。
- Eureka客戶端嘗試與同一區域中的Eureka Server通信。如果在與服務器通信時遇到問題,或者該服務器不存在於同一區域中,則客戶端將故障轉移到其他區域中的服務器。
- 服務器開始接收流量後,在服務器上執行的所有操作都將複製到服務器知道的所有對等節點。如果某個操作由於某種原因失敗,那麼該信息將在下一個檢測信號上進行協調,該檢測信號也會在服務器之間複製。
- 當Eureka服務器啓動時,它將嘗試從相鄰節點獲取所有實例註冊表信息。如果從節點獲取信息有問題,則服務器會在放棄之前嘗試所有對等節點。如果服務器能夠成功獲取所有實例,則它將基於該信息設置應接收的續訂閾值。如果有任何時間,續訂降到爲此值配置的百分比以下(15分鐘內低於85%),服務器將停止實例過期以保護當前實例註冊表信息。
- 在Netflix中,以上保護措施稱爲自我保護模式,主要用於在一組客戶端和Eureka Server之間存在網絡分區的情況下的保護措施。在這些情況下,服務器嘗試保護它已經擁有的信息。在大規模中斷的情況下,可能存在一些場景,這可能會導致客戶端獲取不再存在的實例。客戶端必須確保它們對eureka服務器具有彈性,可以返回不存在或無響應的實例。在這些情況下,最好的保護是快速超時並嘗試其他服務器。
- 在這種情況下,如果服務器無法從相鄰節點獲取註冊表信息,它將等待幾分鐘(5分鐘),以便客戶端可以註冊其信息。服務器通過將流量僅偏向一組實例並導致容量問題,努力不向客戶端提供部分信息。
- Eureka服務器使用此處所述的Eureka客戶端與服務器之間使用的相同機制相互通信。
- 另外值得注意的是,可以在服務器上調整多種配置,包括在需要時進行服務器之間的通信。
對等之間的網絡中斷期間會發生什麼?- 如果對等點之間發生網絡中斷,則可能發生以下情況
- 對等方之間的心跳複製可能會失敗,並且服務器會檢測到這種情況,並進入保護當前狀態的自保留模式。
- 註冊可能發生在孤立的服務器上,某些客戶端可能會反映新的註冊,而其他客戶端則可能沒有。
- 網絡連接恢復到穩定狀態後,情況會自動更正。當對等方能夠正常通信時,註冊信息會自動傳輸到不具有它們的服務器。
- 最重要的是,在網絡中斷期間,服務器會嘗試儘可能地具有彈性,但是在此期間,客戶端可能會對服務器有不同的看法。
我們知道Eureka 是一個服務治理框架,支持服務註冊和服務發現。
也就是說,每個微服務實例都需要以每30秒一次的頻率將自己註冊的有效期限續簽到Eureka Server.
這個時間間隔可以通過如下參數進行調整
#default second is 30 eureka.instance.leaseRenewalIntervalInSeconds=30
- Renews (last min):表示最近一分鐘從Eureka 實例收到的續訂次數
- Renews threshold:續訂閥值,Eureka服務器期望每分鐘從Eureka實例收到的續訂閥值,初始化值最低爲1 (次)
服務註冊中心不註冊自己: 2*(n+1)*0.85
只取整數部分
服務註冊中心註冊自己: 2*n*0.85
只取整數部分
如下圖所示:
- 如果
registerWithEureka
設置成false,eureka.instance.leaseRenewalIntervalInSeconds
設置成30- 然後運行兩個微服務實例,兩個微服務實例將會每分鐘發送4個續訂,即
Renews (last min):4
- Eureka Server 最小的閥值是1, 所以閥值是5(此數字將乘以一個因子
eureka.server.renewalPercentThreshold
,將在後面討論)
根據公式計算閥值:2*(2+1)*0.85= 5.1
只取整數部分5
SELF PRESERVATION MODE
: if Renews (last min) 小於等於 Renews threshold, SELF PRESERVATION MODE(自我保護模式)將會被激活
因此在上例中,由於閾值爲5,所以激活了SELF PRESERVATION MODE(自我保護模式),但是Eureka服務器每分鐘只能接收4次更新。
- 問題一:自我保護機制的目的是什麼?文檔中說客戶端可以獲取不存在的實例?建議打開還是關閉
- “
SELF PRESERVATION MODE
(自我保護模式)”旨在避免不良的網絡連接失敗。- Eureka實例A和B之間的連通性很好,但是B由於連接中斷而未能在短時間內將其租約續簽到Eureka服務器,此時Eureka服務器不能簡單地將實例B踢出去。 儘管B可用,但A不會從Eureka服務器獲得可用的註冊服務。 因此,這是“自我保存模式”的目的
- 最好將其打開
- 問題二:我有一個單一的Eureka 服務器然後配置了
registerWithEureka: false
防止它註冊到其他服務器上,爲什麼它會顯示在閾值計數中?
- 最小閾值1 是代碼中寫死的,
registerWithEureka
設置爲false,因此將沒有Eureka實例寄存器,閾值爲1。- 在生產環境中,通常我們部署兩個Eureka服務器,並將
registerWithEureka
設置爲true。- 因此,閾值將爲2,Eureka服務器將向其自身續租兩次(每分鐘兩次),因此續訂不超過閾值將不會有問題。
- 問題三:對於我啓動的每個客戶,閾值計數都增加+2。 我猜是因爲他們每分鐘發送2條更新消息,對嗎?
# 定義每分鐘發送到服務器的更新數 default is 30 也就是每30秒續訂一次
eureka.instance.leaseRenewalIntervalInSeconds=30
# default is 0.85
eureka.server.renewalPercentThreshold=0.85
- 問題四:Eureka服務器從不發送續訂,而最後一分鐘續訂始終低於閾值。 這正常嗎?
renew threshold 5
rewnews last min: (client1) 2 + (client2) 2 -> 4
根據公式計算閥值:2*(2+1)*0.85= 5.1
只取整數部分5
是的,這很正常,因爲閾值初始值設置爲1。因此,如果registerWithEureka設置爲false,則續訂始終低於閾值。
1.3 解決方案
- Renews (last min):表示最近一分鐘從Eureka 實例收到的續訂次數
- Renews threshold:續訂閥值,Eureka服務器期望每分鐘從Eureka實例收到的續訂閥值,初始化值最低爲1
if Renews (last min) 少於 Renews threshold, SELF PRESERVATION MODE(自我保護模式)將會被激活
對於出現的錯誤提示信息,可以修改Eureka 服務註冊中心的配置文件如下所示進行修復:
# 默認值是true
eureka.server.enable-self-preservation=true
# default is 30
eureka.instance.leaseRenewalIntervalInSeconds=30
# default is 0.85 we can set the value to 0.49
eureka.server.renewalPercentThreshold=0.49
參數修改後重啓,需要等待至少一分鐘後方可看到效果。
n 表示註冊到服務註冊中心到微服務個數
- 如果服務註冊中心不註冊自身,
- 閥值計算公式:
2*(n+1)*0.85
結果只取整數部分- 如果服務註冊中心註冊自身
- 閥值計算公式:
2*n*0.85
結果只取整數部分
如果n 等於3 ,不註冊自身,按照默認值計算閥值
-
2*(3+1)*0.85= 6.8
-> 6 == 實際每分鐘續訂次數 6 =2*3
-
2*(3+1)*0.49= 3.92
-> 3 < 實際每分鐘續訂次數 6 =2*3
這也是爲什麼修改那個參數爲0.49 就可以解決這個問題的原因。
網上有很多說法,我總結下這兩種設置的本質區別:
- 如果將這個值設置爲false 表示當一個微服務和當前的服務註冊中心處於弱網絡(也就是說網絡信號很差或有波動)環境的時候,可能出現當前服務註冊中心訪問狀態不佳或微服務在短暫時間內沒有續訂成功的情況,如果服務註冊中心強行立即從列表中移除這個微服務實例是不太好的,會影響其他微服務的調用,畢竟如果只是因爲一些網絡波動就導致將微服務被移除(有些過於殘暴)因此建議,當只有一個微服務的時候才需要將建議將它設置爲false
- 如果將這個值設置爲true,表示當一個微服務處於弱網絡環境的時候,其他微服務仍然可以獲取這個微服務的實例列表,但是如果超過一定時間還是無法提供服務,那麼將其剔除,其他微服務不可以調用它。
解決上述問題的更好的建議是:
- 如果生產環境最好部署至少兩臺服務註冊中心,然後開啓自注冊,當一個服務註冊中心不穩時候快速切換其他服務註冊中心,實現高可用的目的。
- 續訂降到爲此值配置的百分比以下(15分鐘內低於85%),服務器將停止實例過期以保護當前實例註冊表信息,如果覺得有必要也可以調整閥值檢測比例爲0.49.
1.4參考資料
- Eureka never unregisters a service
- EurekaServer: wrongly claims self preservation is turned off when renewal threshold is low
- Understanding Spring Cloud Eureka Server self preservation and renew threshold
- Understanding Eureka Peer to Peer Communication
- Spring Cloud Netflix Eureka - The Hidden Manual