Kitex 負載均衡

2022-04-26 15:16 更新

負載均衡

Kitex 默認提供了兩種 LoadBalancer(下面簡稱 lb):

  • WeightedRandom
  • ConsistentHash

Kitex 默認使用的是 WeightedRandom。

WeightedRandom

顧名思義,這個 lb 使用的是基于權(quán)重的隨機策略,也是 Kitex 的默認策略。

這個 lb 會依據(jù)實例的權(quán)重進行加權(quán)隨機,并保證每個實例分配到的負載和自己的權(quán)重成比例。

如果所有的實例的權(quán)重都一樣,Kitex 針對這個場景做了特殊優(yōu)化,會使用一個純隨機的實現(xiàn),來避免加權(quán)計算的一些額外開銷,所以不需要擔心這個場景下的性能。

ConsistentHash

簡介

一致性哈希主要適用于對上下文(如實例本地緩存)依賴程度高的場景,如希望同一個類型的請求打到同一臺機器,則可使用該負載均衡方法。

如果你不了解什么是一致性哈希,或者不知道帶來的副作用,請勿使用一致性哈希。

使用

如果要使用一致性哈希,可以在初始化 client 的時候傳入 ?client.WithLoadBalancer(loadbalance.NewConsistBalancer(loadbalance.NewConsistentHashOption(keyFunc)))?

?ConsistentHashOption ?定義如下:

type ConsistentHashOption struct {
    GetKey KeyFunc

    // 是否使用 replica
    // 如果使用,當請求失?。ㄟB接失敗)后會依次嘗試 replica
    // 會帶來額外內(nèi)存和計算開銷
    // 如果不設(shè)置,那么請求失?。ㄟB接失敗)后直接返回
    Replica uint32

    // 虛擬節(jié)點數(shù)
    // 每個真實節(jié)點對應(yīng)的虛擬節(jié)點的數(shù)量
    // 這個數(shù)值越大,內(nèi)存和計算代價越大,負載越均衡
    // 當節(jié)點數(shù)多時,可以適當設(shè)小一些;反之可以適當設(shè)大一些
    // 推薦 VirtualFactor * Weight(如果 Weighted 為 true)的中位數(shù)在 1000 左右,負載應(yīng)當已經(jīng)很均衡了
    // 推薦 總虛擬節(jié)點數(shù) 在 2000W 以內(nèi)(1000W 情況之下 build 一次需要 250ms,不過為后臺 build 理論上 3s 內(nèi)均無問題)
    VirtualFactor    uint32

    // 是否要遵循 Weight 進行負載均衡
    // 如果為 false,對于每個 instance 都會忽略 Weight,均生成 VirtualFactor 個虛擬節(jié)點,進行無差別負載均衡
    // 如果為 true,對于每個 instance 會生成 instance.Weight() * VirtualFactor 個虛擬節(jié)點
    // 需要注意,對于 weight 為 0 的 instance,無論 VirtualFactor 為多少,均不會生成虛擬節(jié)點
    // 建議設(shè)為 true,不過要注意適當調(diào)小 VirtualFactor
    Weighted bool

    // 是否進行過期處理
    // 實現(xiàn)會緩存所有的 Key
    // 如果永不過期會導(dǎo)致內(nèi)存一直增長
    // 設(shè)置過期會導(dǎo)致額外性能開銷
    // 目前的實現(xiàn)是每分鐘掃描刪除一次,以及實例發(fā)生變動 rebuild 時刪除一次
    // 建議一定要設(shè)置,值不要小于一分鐘
    ExpireDuration time.Duration
}

要注意,如果 GetKey 是 nil 或者 VirtualFactor 是 0,會 panic。

性能

經(jīng)過測試,在 weight 為 10、VirtualFactor 為 100 的情況之下,不同 instance 數(shù)量的 build 性能如下:

BenchmarkNewConsistPicker_NoCache/10ins-16                 6565        160670 ns/op      164750 B/op          5 allocs/op
BenchmarkNewConsistPicker_NoCache/100ins-16                 571       1914666 ns/op     1611803 B/op          6 allocs/op
BenchmarkNewConsistPicker_NoCache/1000ins-16                 45      23485916 ns/op    16067720 B/op         10 allocs/op
BenchmarkNewConsistPicker_NoCache/10000ins-16                 4     251160920 ns/op    160405632 B/op        41 allocs/op

所以當有 10000 個 instance,每個 instance weight 為 10,VirtualFactor 為 100 的情況之下(總虛擬節(jié)點數(shù) 1000W),build 一次需要 251 ms。

build 和 請求 信息都會被緩存,所以一次正常請求(不需要 build)的時延和節(jié)點多少無關(guān),如下:

BenchmarkNewConsistPicker/10ins-16             12557137            81.1 ns/op         0 B/op          0 allocs/op 
BenchmarkNewConsistPicker/100ins-16            13704381            82.3 ns/op         0 B/op          0 allocs/op 
BenchmarkNewConsistPicker/1000ins-16           14418103            81.3 ns/op         0 B/op          0 allocs/op 
BenchmarkNewConsistPicker/10000ins-16          13942186            81.0 ns/op         0 B/op          0 allocs/op

注意事項 

  1. 下游節(jié)點發(fā)生變動時,一致性哈希結(jié)果可能會改變,某些 key 可能會發(fā)生變化;
  2. 如果下游節(jié)點非常多,第一次冷啟動時 build 時間可能會較長,如果 rpc 超時短的話可能會導(dǎo)致超時;
  3. 如果第一次請求失敗,并且 Replica 不為 0,那么會請求到 Replica 上;而第二次及以后仍然會請求 第一個 實例。

負載的均衡度

經(jīng)過測試,當下游實例為 10 個時,如果 VirtualFactor 設(shè)置為 1 并且不開啟 Weighted 時,負載非常不均衡,如下:

addr2: 28629
addr7: 13489
addr3: 10469
addr9: 4554
addr0: 21550
addr6: 6516
addr8: 2354
addr4: 9413
addr5: 1793
addr1: 1233

當 VirtualFactor 設(shè)置為 10 時,負載如下:

addr7: 14426
addr8: 12469
addr3: 8115
addr4: 8165
addr0: 8587
addr1: 7193
addr6: 10512
addr9: 14054
addr2: 9307
addr5: 7172

可以看出比 VirtualFactor 為 1 時要好很多。

當 VirtualFactor 為 1000 時,負載如下:

addr7: 9697
addr5: 9933
addr6: 9955
addr4: 10361
addr8: 9828
addr0: 9729
addr9: 10528
addr2: 10121
addr3: 9888
addr1: 9960

可以看出此時負載基本均衡。

再來看看帶 Weight 的情況,我們設(shè)置 addr0 的 weight 為 0,addr1 的 weight 為 1,addr2 的 weight 為 2……以此類推。

設(shè)置 VirtualFactor 為 1000,得到負載結(jié)果如下:

addr4: 8839
addr3: 6624
addr6: 13250
addr1: 2318
addr8: 17769
addr2: 4321
addr5: 11099
addr9: 20065
addr7: 15715

可以看到基本是和 weight 的分布一致。在這里沒有 addr0 是因為 weight 為 0 是不會被調(diào)度到的。

綜上,提高 VirtualFactor,可以使得負載更加均衡,但是也要注意會增加性能開銷,需要找個平衡點。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號