首先本文所有的 source code 基於 kubernetes 1.19 版本,所有 source code 為了版面的整潔會精簡掉部分 log 相關的程式碼,僅保留核心邏輯,如果有見解錯誤的地方,還麻煩觀看本文的大大們提出,感謝!
本篇文章是基於上一篇 Kubernetes util tool 使用 Backoff 抖了一下的拓展 ,主要會看到 kubernetes 除了透過 Jittered Backoff Manager Impl 實作了 BackoffManager 之外,還額外實作了另外一種 Exponential Backoff Manager Impl命名方式也十分 java xD。
我們也先複習一下上一張有提到的 BackoffManager,先以一個情境來描述為甚麼要backoff !
當 client 發送請求給 server 如果有可重試類型的失敗那我們就會重新發起請求,but!
這裡有個問題如果說我們寫的 client 一次打出去的請求有上百個甚至上千個呢? client 的重試可能會把 server 打掛,所以需要設計一個 backoff 讓重試的請求每次退後一點,每次退後一點(這裡的退後可以想像成重試時間垃長一點)。
|
|
是不是非常的簡單的,實作 BackoffManager 的物件只要實作 Backoff() clock.Timer 就好了~
我們來看一下今天要講的主題 exponentialBackoffManagerImpl 的資料結構吧!
struct
|
|
其中比較疑慮的參數應該是 backoff 竟然是一個物件,那…到底是長圓的還是扁的?就讓我們來瞧瞧吧!
Backoff
|
|
看完了資料結構就要接著看 Backoff 的實作囉,這部分有點小複雜!
step
這裡我看了滿久的,基本上要有幾個情境才能看得出來他的應用,我們先來看程式碼等等再來看使用情境。
|
|
Step function 大概會包含以下四種情境,需要搭配著 code 閱讀會比較好理解一點。
以下情境全部 b.Duration 保持 0.5 s
- 僅設定 step
- step 設定 4 次
程式流程會怎麼樣呢?
- step 設定 4 次
第一次近來來 step – (step=3),duration := b.Duration <0.5>,回傳 duration 0.5 s。
第二次近來來 step – (step=2),duration := b.Duration <0.5>,回傳 duration 0.5 s。
第三次近來來 step – (step=1),duration := b.Duration <0.5>,回傳 duration 0.5 s。
第四次近來來 step – (step=0),duration := b.Duration <0.5>,回傳 duration 0.5 s。
- 僅設定 step 與 factor
- step 設定 4 次
- factor 設定 2
程式流程會怎麼樣呢?
-
第一次近來來
step – (step=3)
duration := b.Duration <0.5>
b.Duration = b.Duration<0.5> * factor <2>
回傳 duration 0.5 s。 -
第二次近來來
step – (step=2)
duration := b.Duration <1>
b.Duration = b.Duration<1> * factor <2>
回傳 duration 1 s。 -
第三次近來來
step – (step=1)
duration := b.Duration <2>
b.Duration = b.Duration<2> * factor <2>
回傳 duration 2 s。 -
第四次近來來
step – (step=0)
duration := b.Duration <2>
b.Duration = b.Duration<4> * factor <2>
回傳 duration 4 s。
- 設定 step 、 factor 與 Cap
- step 設定 4 次
- factor 設定 2
- Cap 設定 2 s
程式流程會怎麼樣呢?
-
第一次近來
step – (step=3)
duration := b.Duration <0.5>
b.Duration = b.Duration<0.5> * factor <2>
回傳 duration 0.5 s。 -
第二次近來
step – (step=2)
duration := b.Duration <1>
b.Duration = b.Duration<1> * factor <2>
回傳 duration 1 s。 -
第三次近來
step – (step=1)
duration := b.Duration <2>
b.Duration = b.Duration<2> * factor <2>
b.Duration = b.Cap <2>
b.Step = 0
回傳 duration 2 s。 -
第四次近來
duration := b.Duration <2>
回傳 duration 2 s。
- 設定 step 、 factor 、 Cap 與 jitter
- step 設定 4 次
- factor 設定 2
- Cap 設定 2 s
- jitter 設定 1 s
程式流程會怎麼樣呢?
-
第一次近來
step – (step=3)
duration := b.Duration <0.5>
b.Duration = b.Duration<0.5> * factor <2>
假設 jitter 回傳的結果為 0.6
回傳 duration 0.6 s。 -
第二次近來
step – (step=2)
duration := b.Duration <1>
b.Duration = b.Duration<1> * factor <2>
假設 jitter 回傳的結果為 1.3
回傳 duration 1.3 s。 -
第三次近來
step – (step=1)
duration := b.Duration <2>
b.Duration = b.Duration<2> * factor <2>
b.Duration = b.Cap <2>
b.Step = 0
假設 jitter 回傳的結果為 2.6
回傳 duration 2.6 s。 -
第四次近來
假設 jitter 回傳的結果為 4.1
回傳 duration 4.1 s。
看完比較神秘的 backoff 物件後 要回來理解要如何把 Exponential Backoff Manager 建立出來,觀察他的 new function 有沒有偷藏什麼!
new function
在這之前先再次複習一下 exponentialBackoffManagerImpl 的資料結構
|
|
複習完了 exponentialBackoffManagerImpl 的資料結構後,我們馬上來看看怎麼新增這個物件吧!
|
|
Backoff
瞭解了 exponentialBackoffManagerImpl 怎麼新增物件後,趕緊來看實作的部分廢話就不多說直接上 code !
|
|
exponentialBackoffManagerImpl Backoff function 的重點基本上在於 backoff 物件如何計算延遲時間,以及當執行時間超過 backoffResetDuration 就要將 backoff 物件設定成預設的閥值。
小結
簡單的來看這個 kubernetes utils tool ,屬於 wait package 的一部分主要實作 backoff 邏輯,防止 client 端因為大量的請求打壞 server ,透過上一篇提到的 jitter 結合本篇的 exponential Backoff 可以讓 user 只要輕鬆進行幾個簡單的設定例如 initBackoff 基礎延遲時間 ,backoffFactor 延遲倍數因子 , jitter 抖動範圍, maxBackoff 最大延遲時間 以及當多久沒有呼叫 backoff 需要重置的 resetDuration 就能獲得有 backoff 功能 clock ,整個過程相當的簡單~