深度解析Eureka的自我保护机制
原創不易,轉載請注明出處
文章目錄
- 1.自我保護機制介紹
- 2.實現原理
- 3.源碼解析
- 3.1`期望心跳數` 與 `我心里能接受的最小心跳數`
- 3.1.1 初始化
- 3.1.2 服務注冊
- 3.1.3 服務下線
- 3.2 關于計數器
- 3.2.1 計數器初始化
- 3.2.2 心跳計數
- 3.3 關于自我保護模式的判斷
- 3.4 eureka web中那行大紅字
- 3.5 觸發自我保護對過期下線的影響
- 4.一張圖
- 總結
1.自我保護機制介紹
想必用過eureka 的同學都在eureka web控制臺見過這么一行大紅字,我現在還能想起來第一次用eureka 出現這個的心里的那種感覺,什么東西,這么顯眼,然后就很懵逼,立馬搜了一下這個是什么鬼,就搜到說eureka自我保護機制觸發了,說是 “eureka 在運行期間會去統計心跳失敗比例在 15 分鐘之內是否低于 85%,如果低于 85%,eureka 會將這些實例保護起來,讓這些實例不會過期”(需要注意這句話的前半部分,我們這篇文章將用源碼推翻它),其實就是某段時間內收到心跳數量低于期望心跳數量85%,就會觸發這個自我保護機制,這個時候,服務實例將不會被過期。
2.實現原理
一個核心原理:實際收到的心跳 小于 我心里能接受的最小心跳數 ,這個時候就會觸發eureka 自我保護機制
兩個概念(都很好理解):
有了 期望心跳數 與 最小心跳數閾值,我們現在還差的是啥?
那就是統計收到的心跳數
比如說我專門有個計數器,然后以一個時間單位為一個窗口,就是統計每分鐘收到的心跳次數(續約次數),其實光有收集當前分鐘心跳數的計數器還不夠,總不能拿當前分鐘的心跳數與心里能接受的最小心跳數 做比較吧,那分鐘開始的時候,肯定會觸發這個自我保護機制(畢竟分鐘開始的時候,沒收到多少心跳)
這個時候一個計數器就不夠了,還得需要一個,一個用于統計當前分鐘收到的心跳數量,一個用于存儲上一分鐘收到的心跳數,然后拿上一分鐘收到的心跳數 與 心里能接受的最小心跳數 做比較,然后小于心里能接受的最小心跳數,就觸發自我保護機制。
有了2個心跳計數器,還不夠,還缺一個定時器,然后每分鐘執行一次將 當前分鐘收集到的心跳數 給 存儲上一分鐘這個計數器上,然后將當前分鐘計數器清0,表示開啟新一輪的計數。
到這里,其實大體上就已經講清楚了,但是還有幾個點
現在解答一下:
好了,以上就是eureka 自我保護機制的實現原理了,只不過我用自己的話將代碼翻譯了一遍,如果還是不能明白,可以看一下第4節的那張圖。接下來我們就要看一下源碼了
3.源碼解析
3.1期望心跳數 與 我心里能接受的最小心跳數
先看一下關于 期望心跳數 與 我心里能接受的最小心跳數 變量的定義
在 eureka-core 項目的注冊表抽象類AbstractInstanceRegistry 中定義了這兩個變量
接著看下初始化,服務注冊,服務下線 期望心跳數 與 我心里能接受的最小心跳數 變動。
3.1.1 初始化
eureka server在啟動的時候,會進行初始化,它會到其他server 節點上同步一下注冊表,然后注冊到自己本地的注冊表中,這個時候會返回一個同步數量count,后面注冊表中的這兩個變量會根據這個count計算出來
先是同步注冊表,返回同步實例的數量。
接著就是調用注冊表的 openForTraffic 方法,初始化這兩個變量,改變applicationInfoManager 為up狀態,完成注冊表 初始化之后的動作
這里期望心跳數 直接就是同步實例數量*2 ,我心里能接受的最小心跳數 是期望心跳數 * 0.85(默認是0.85)
3.1.2 服務注冊
在注冊表抽象類AbstractInstanceRegistry 中的register方法中
可以看到 期望心跳數 +2 ,然后 我心里能接受的最小心跳數 重新算了一遍。
3.1.3 服務下線
這個是在注冊表抽象類AbstractInstanceRegistry 的實現類PeerAwareInstanceRegistryImpl中的cancel 方法做的處理
它這里有個很大的問題就是這個+2 和-2 直接寫死了,如果我心跳間隔改變了,這個時候不是30s發一次心跳了,變成了1分鐘一次,然后eureka 就會一直處于自我保護機制中。
3.2 關于計數器
3.2.1 計數器初始化
eureka server 啟動的時候,會執行一堆初始化,這個是在EurekaBootstrap中的,之后就是創建注冊表,在注冊表抽象類AbstractInstanceRegistry的構造方法中創建了這個計數器。
然后再初始化最后面調用了一下注冊表的openForTraffic 方法,初始化期望心跳數 與 我心里能接受的最小心跳數 這兩個變量,改變applicationInfoManager 為up狀態,完成注冊表 初始化之后的動作,就在注冊表 初始化之后的動作里面啟動了計數器。
先來看下 MeasuredRate 這類中關鍵的幾個成員變量:
它的start 方法其實就是啟動這個定時任務
它這里是1分鐘執行一次,就是sampleInterval 這個成員決定的,這個成員實在創建這個對象的傳過來的,然后就是1分鐘。
看下這個畫紅框的代碼,其實就是將 當前分鐘收集到的心跳數 給 存儲上一分鐘這個計數器 lastBucket上,然后將當前分鐘計數器 currentBucket清0,表示開啟新一輪的計數。
3.2.2 心跳計數
其實每收到一個心跳(續約),都會給currentBucket 這變量自增1,我們看一下代碼
3.3 關于自我保護模式的判斷
上面就是就是自我保護模式的判斷了,很清楚。
3.4 eureka web中那行大紅字
在resource 的header.jsp中有這么幾行
先是調用注冊表的isBelowRenewThresold 方法判斷是不是觸發了自我保護機制
要想顯示那行觸發自我保護機制的大紅字,需要 系統啟動了5分鐘以上,而且觸發了自我保護機制,其實還需要isSelfPreservationModeEnabled 這個參數是true,這樣子才會顯示這個觸發自我保護的大紅字
3.5 觸發自我保護對過期下線的影響
在注冊表 postInit方法中,其實還啟動一個定時任務,掃描那些過期的實例,然后進行服務下線動作,這里主要是介紹觸發自我保護對過期下線的影響,不會深入剖析服務掃描下線這一堆的東西
這個定時任務是1分鐘執行一次的。
進入這個evict 方法中。
如果觸發了自我保護機制就不往下走了,其實下面就是掃描注冊表中所有的實例信息,然后看看過沒過期,過期就走服務下線邏輯。我們來看下這個isLeaseExpirationEnabled方法的實現。
如果沒有啟用這個自我保護機制的話,直接通過,走下面服務掃描過期的邏輯。如果啟用了,還用判斷 收到的心跳數大于期望最小心跳數 ,這個時候才能繼續往下走,如果是小于的話,就是觸發自我保護機制了,就不會再往下走了,也就是不會再掃描下線過期的實例。
4.一張圖
總結
本篇文章主要是介紹了eureka自我保護機制的實現原理,不管是語言描述,還是代碼剖析,都已經很明了了。我沒有找到所謂的 15分鐘內
心跳失敗比例小于85% 就是觸發自我保護機制,在源碼中,我只分析出 你上一分鐘心跳數 低于 期望心跳數的85% 就會觸發自我保護機制,我不知道他們所謂的15分鐘是哪里的,我只相信源碼出真知,然后這里還發現計算期望心跳數 的硬編碼問題,如果你心跳間隔改變了,不是30s了,就很容易出現bug。
總結
以上是生活随笔為你收集整理的深度解析Eureka的自我保护机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 书籍借鉴
- 下一篇: Msp430 bsl program