Spring Cloud Eureka 自我保護(hù)機(jī)制

Eureka Server 在運(yùn)行期間會(huì)去統(tǒng)計(jì)心跳失敗比例在 15 分鐘之內(nèi)是否低于 85%,如果低于 85%,Eureka Server 會(huì)將這些實(shí)例保護(hù)起來,讓這些實(shí)例不會(huì)過期,但是在保護(hù)期內(nèi)如果服務(wù)剛好這個(gè)服務(wù)提供者非正常下線了,此時(shí)服務(wù)消費(fèi)者就會(huì)拿到一個(gè)無效的服務(wù)實(shí)例,此時(shí)會(huì)調(diào)用失敗,對(duì)于這個(gè)問題需要服務(wù)消費(fèi)者端要有一些容錯(cuò)機(jī)制,如重試,斷路器等。

我們?cè)趩螜C(jī)測試的時(shí)候很容易滿足心跳失敗比例在 15 分鐘之內(nèi)低于 85%,這個(gè)時(shí)候就會(huì)觸發(fā) Eureka 的保護(hù)機(jī)制,一旦開啟了保護(hù)機(jī)制,則服務(wù)注冊(cè)中心維護(hù)的服務(wù)實(shí)例就不是那么準(zhǔn)確了,此時(shí)我們可以使用eureka.server.enable-self-preservation=false來關(guān)閉保護(hù)機(jī)制,這樣可以確保注冊(cè)中心中不可用的實(shí)例被及時(shí)的剔除(不推薦)。

自我保護(hù)模式被激活的條件是:在 1 分鐘后,Renews (last min) < Renews threshold。

這兩個(gè)參數(shù)的意思:

  • Renews thresholdEureka Server 期望每分鐘收到客戶端實(shí)例續(xù)約的總數(shù)。
  • Renews (last min)Eureka Server 最后 1 分鐘收到客戶端實(shí)例續(xù)約的總數(shù)

具體的值,我們可以在 Eureka Server 界面可以看到:

image

可以看到,我們部署了 3 個(gè) Eureka Server(自注冊(cè)模式),另外,又部署 7 個(gè)服務(wù),注冊(cè)到 Eureka Server 集群,參數(shù)值分別為:

  • Renews threshold:17
  • Renews (last min):20

下面說下Renews thresholdRenews threshold具體計(jì)算方式。

Renews threshold 計(jì)算代碼:

this.expectedNumberOfRenewsPerMin = count * 2;
this.numberOfRenewsPerMinThreshold = (int) (this.expectedNumberOfRenewsPerMin * serverConfig.getRenewalPercentThreshold());

count表示服務(wù)的數(shù)量,如果 Eureka Server 開啟自注冊(cè)模式,也算一個(gè)服務(wù),比如我們上面的示例,count的值就是 10(3 個(gè)自注冊(cè)服務(wù) + 7 個(gè)獨(dú)立服務(wù)),serverConfig.getRenewalPercentThreshold()默認(rèn)是 0.85(可以通過eureka.server.renewal-percent-threshold配置)。

所以,根據(jù)上面的分析,我們可以計(jì)算出Renews threshold的值:(int)(10 * 2 * 0.85) = (int)17 = 17。

Renews (last min)計(jì)算方式:count * 2,數(shù)值 2 表示每 30 秒 1 個(gè)心跳,每分鐘 2 個(gè)心跳的固定頻率因子,所以具體值為:10 * 2 = 20。

如果在 1 分鐘后,Renews (last min) < Renews threshold,默認(rèn)需等待 5 分鐘(可以通過eureka.server.wait-time-in-ms-when-sync-empty配置),即 5 分鐘后你會(huì)看到下面的提示信息:

image
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.

解決方式有三種:

  • 關(guān)閉自我保護(hù)模式(eureka.server.enable-self-preservation設(shè)為false),不推薦。
  • 降低renewalPercentThreshold的比例(eureka.server.renewal-percent-threshold設(shè)置為0.5以下,比如0.49),不推薦。
  • 部署多個(gè) Eureka Server 并開啟其客戶端行為(eureka.client.register-with-eureka不要設(shè)為false,默認(rèn)為true),推薦。

Eureka 的自我保護(hù)模式是有意義的,該模式被激活后,它不會(huì)從注冊(cè)列表中剔除因長時(shí)間沒收到心跳導(dǎo)致租期過期的服務(wù),而是等待修復(fù),直到心跳恢復(fù)正常之后,它自動(dòng)退出自我保護(hù)模式。這種模式旨在避免因網(wǎng)絡(luò)分區(qū)故障導(dǎo)致服務(wù)不可用的問題。例如,兩個(gè)客戶端實(shí)例 C1 和 C2 的連通性是良好的,但是由于網(wǎng)絡(luò)故障,C2 未能及時(shí)向 Eureka 發(fā)送心跳續(xù)約,這時(shí)候 Eureka 不能簡單的將 C2 從注冊(cè)表中剔除。因?yàn)槿绻蕹?,C1 就無法從 Eureka 服務(wù)器中獲取 C2 注冊(cè)的服務(wù),但是這時(shí)候 C2 服務(wù)是可用的。

所以,Eureka 的自我保護(hù)模式最好還是開啟它。


Eureka Server 單機(jī)版配置示例:

debug: true
spring:
  application:
    name: eureka-server
logging:
  level:
    com.netflix.eureka: 'off'
    com.netflix.discovery: 'off'
server:
  port: 8100
eureka:
  instance:
    hostname: localhost
  server:
    enable-self-preservation: false #關(guān)閉自我保護(hù)機(jī)制
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,569評(píng)論 19 139
  • Demo 源碼下載 本案例為源碼分支的 eureka 分支 服務(wù)發(fā)現(xiàn)概述 服務(wù)發(fā)現(xiàn)機(jī)制是為了解決硬網(wǎng)絡(luò)編碼問題,服...
    聰明的奇瑞閱讀 5,247評(píng)論 0 13
  • p103-113 字詞 1. pull off The play is only a couple of days...
    莉莉安lee_1dab閱讀 718評(píng)論 0 0
  • 雖然我的夢想沒有《神秘巨星》里的主人工的夢想偉大,但是媽媽卻是那個(gè)幫助我守護(hù)夢想的那個(gè)人! 原來每個(gè)優(yōu)秀的...
    流年七里香農(nóng)莊閱讀 210評(píng)論 0 1

友情鏈接更多精彩內(nèi)容