在 Kitex 中,提供了兩種 LoadBalancer:
這兩種 LoadBalancer 能覆蓋絕大多數(shù)的應(yīng)用場(chǎng)景,如果業(yè)務(wù)有一些 Corner Case 無(wú)法覆蓋到,可以選擇自己自定義 LoadBalancer。
LoadBalancer 接口在 ?pkg/loadbalance/loadbalancer.go
? 中,具體定義如下:
// Loadbalancer generates pickers for the given service discovery result.
type Loadbalancer interface {
GetPicker(discovery.Result) Picker
// 名稱需要唯一
Name() string
}
可以看到 LoadBalancer 獲取到一個(gè) Result 并且生成一個(gè)針對(duì)當(dāng)次請(qǐng)求的 Picker,Picker 定義如下:
// Picker picks an instance for next RPC call.
type Picker interface {
Next(ctx context.Context, request interface{}) discovery.Instance
}
有可能在一次的 rpc 請(qǐng)求中,所選擇的實(shí)例連接不上,而要進(jìn)行重試,所以設(shè)計(jì)成這樣。
如果說(shuō)已經(jīng)沒(méi)有實(shí)例可以重試了,Next 方法應(yīng)當(dāng)返回 nil。
除了以上接口之外,還有一個(gè)比較特殊的接口,定義如下:
// Rebalancer is a kind of Loadbalancer that performs rebalancing when the result of service discovery changes.
type Rebalancer interface {
Rebalance(discovery.Change)
Delete(discovery.Change)
}
如果 LoadBalancer 支持 Cache,務(wù)必實(shí)現(xiàn) Rebalancer 接口,否則服務(wù)發(fā)現(xiàn)變更就無(wú)法被通知到了。
Kitex client 會(huì)在初始化的時(shí)候執(zhí)行以下代碼來(lái)保證當(dāng)服務(wù)發(fā)現(xiàn)變更時(shí),能通知到 Rebalancer:
if rlb, ok := balancer.(loadbalance.Rebalancer); ok && bus != nil {
bus.Watch(discovery.DiscoveryChangeEventName, func(e *event.Event) {
change := e.Extra.(*discovery.Change)
rlb.Rebalance(*change)
})
}
如果是動(dòng)態(tài)服務(wù)發(fā)現(xiàn),那么盡可能實(shí)現(xiàn)緩存,可以提高性能;
如果使用了緩存,那么務(wù)必實(shí)現(xiàn) Rebalancer 接口,否則當(dāng)服務(wù)發(fā)現(xiàn)變更時(shí)無(wú)法收到通知;
使用了 Proxy 場(chǎng)景下,不支持自定義 LoadBalancer。
可以參考一下 Kitex 默認(rèn)的 WeightedRandom 實(shí)現(xiàn)。
更多建議: