This page looks best with JavaScript enabled

Kubernetes util tool 使用 Backoff 抖了一下

 ·  ☕ 3 min read

首先本文所有的 source code 基於 kubernetes 1.19 版本,所有 source code 為了版面的整潔會精簡掉部分 log 相關的程式碼,僅保留核心邏輯,如果有見解錯誤的地方,還麻煩觀看本文的大大們提出,感謝!

有朋友私訊我為什麼關於 kubernetes controller 的Reflector 我在盯著你 ( III )文章還沒出
因為筆者最近事情有點多加上是系列文的最後幾篇,Reflector 有些部分還不是非常了解,既然要 dig controller/operator 的實作就不想輕易的草率帶過。再麻煩各位再等等了,感謝!

Jittered Backoff Manager Impl

今天要來探討的是 kubernetes Jittered Backoff Manager Impl 這個名稱非常 java ,就名稱來看就是抖動的 Backoff Manage 實作,既然是 Backoff Manage 的實作的話,我們就要先來看一下 Backoff Manage 是個什麼樣的狠角色。

BackoffManager

先從名稱來推敲應該是退後管理器,那什麼是退後管理器。
我用一個簡單的範例說明,通常 client 發送請求給 server 如果有可重試類型的失敗那我們就會重新發起請求,but!
這裡有個問題 client 有上百上千個呢? client 的重試可能會把 server 打掛,所以需要設計一個 backoff 讓重試的請求每次退後一點,每次退後一點(這裡的退後可以想像成重試時間垃長一點)。

1
2
3
4
5

// The BackoffManager is supposed to be called in a single-threaded environment.
type BackoffManager interface {
	Backoff() clock.Timer                //回傳一個 clock timer 
}

是不是非常的簡單的,實作 BackoffManager 的物件只要實作 Backoff() clock.Timer 就好了~

我們來看一下今天要講的主題 jitteredBackoffManagerImpl 的資料結構吧!

struct

1
2
3
4
5
6
type jitteredBackoffManagerImpl struct {
	clock        clock.Clock                //給定 clock ,這一個實作應該用不到xD
	duration     time.Duration              //
	jitter       float64
	backoffTimer clock.Timer
}

看完了 jitteredBackoffManagerImpl 的資料結構後我們要來看一下怎麼初始化這個物件,看看有沒有什麼東西偷偷藏在裡面。

new function

1
2
3
4
5
6
7
8
func NewJitteredBackoffManager(duration time.Duration, jitter float64, c clock.Clock) BackoffManager {
	return &jitteredBackoffManagerImpl{
		clock:        c,                     //給定 clock ,這一個實作應該用不到xD
		duration:     duration,              //最少要延遲多久
		jitter:       jitter,                //給定抖動範圍
		backoffTimer: nil,                   //一開始不需要初始化 backoffTimer 會由 使用者呼叫 backoff 時經由計算後再賦值      
	}    
}

看完了如何初始化就是進入 Jittered Backoff Manager Impl 如何實作 BackoffManager !

Backoff

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
func (j *jitteredBackoffManagerImpl) Backoff() clock.Timer {
	backoff := j.getNextBackoff()                     //進來的時候就先計算出 backoff 時間,等等會看到怎麼做的。
	if j.backoffTimer == nil {                        //如果當前沒有 backoff timer 就要賦值
	                                                  //賦與的數就是剛剛get next back off 曲的的時間
		j.backoffTimer = j.clock.NewTimer(backoff)
	} else {
		j.backoffTimer.Reset(backoff)             //如果存在的話需要刷新 backoff 時間
	}
	return j.backoffTimer
}



func (j *jitteredBackoffManagerImpl) getNextBackoff() time.Duration {
	jitteredPeriod := j.duration                       
	if j.jitter > 0.0 {
		jitteredPeriod = Jitter(j.duration, j.jitter)  //等等會看到jitter 在做什麼,這邊只要了解輸入基礎延遲時間跟抖動範圍
		                                               //我們就能到最後要延遲的時間
	}
	return jitteredPeriod
}

Jitter

負責抖動延遲時間的運算

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// Jitter returns a time.Duration between duration and duration + maxFactor * duration.
//
// This allows clients to avoid converging on periodic behavior. If maxFactor
// is 0.0, a suggested default value will be chosen.
func Jitter(duration time.Duration, maxFactor float64) time.Duration {
	//抖動因子參數(抖動範圍)可以自行調整,但不能小於等於0
	if maxFactor <= 0.0 {
		maxFactor = 1.0
	}
    
    //計算方式也很間單 基礎的延遲時間 + 隨機時間*抖動因子*基礎的延遲時間 
	wait := duration + time.Duration(rand.Float64()*maxFactor*float64(duration))
	return wait
}

how to use

由於 kubernetes 沒有直接使用 jitteredBackoffManagerImpl ,只能看一下測試是怎麼寫的。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
func TestJitterBackoffManagerWithRealClock(t *testing.T) {
	//定義抖動的參數,基礎延遲時間為1*time.Millisecond 抖動範圍為0 (這裡等等計算的時候會設定成1)
	backoffMgr := NewJitteredBackoffManager(1*time.Millisecond, 0, &clock.RealClock{})
    
	//測試跑五次,如果抖動的延遲數值小於基礎延遲時間就是測試失敗
	for i := 0; i < 5; i++ {
		start := time.Now()
		//還記得Backoff()回傳一個 clock.Timer 嗎?
		//他就像是一個鬧鐘,當設定的時間到鬧鐘就會響,我們就可以從 channel 被喚醒
		<-backoffMgr.Backoff().C()
		passed := time.Now().Sub(start)
		if passed < 1*time.Millisecond {
			t.Errorf("backoff should be at least 1ms, but got %s", passed.String())
		}
	}
}

小結

kubernetes utils 裡面有許多有趣的工具,像是今天分享就屬於 wiat utils tool 其中一小部分, wait tool 中還有許多有趣的小工具,下一篇會繼續探討 wait 中其他的 Backoff 實作,若是文中有錯誤的見解希望各位在觀看文章的大大們可以指出哪裡有問題,讓我學習改進,謝謝。


Meng Ze Li
WRITTEN BY
Meng Ze Li
Kubernetes / DevOps / Backend

What's on this Page