序
本文次要钻研一下 dubbo-go 的 roundRobinLoadBalance
roundRobinLoadBalance
dubbo-go-v1.4.2/cluster/loadbalance/round_robin.go
const (
// RoundRobin ...
RoundRobin = "roundrobin"
// COMPLETE ...
COMPLETE = 0
// UPDATING ...
UPDATING = 1
)
var (methodWeightMap sync.Map // [string]invokers
state = int32(COMPLETE) // update lock acquired ?
recyclePeriod = 60 * time.Second.Nanoseconds())
func init() {extension.SetLoadbalance(RoundRobin, NewRoundRobinLoadBalance)
}
type roundRobinLoadBalance struct{}
// NewRoundRobinLoadBalance ...
func NewRoundRobinLoadBalance() cluster.LoadBalance {return &roundRobinLoadBalance{}
}
- roundRobinLoadBalance 的 NewRoundRobinLoadBalance 办法创立了 roundRobinLoadBalance
Select
dubbo-go-v1.4.2/cluster/loadbalance/round_robin.go
func (lb *roundRobinLoadBalance) Select(invokers []protocol.Invoker, invocation protocol.Invocation) protocol.Invoker {count := len(invokers)
if count == 0 {return nil}
if count == 1 {return invokers[0]
}
key := invokers[0].GetUrl().Path + "." + invocation.MethodName()
cache, _ := methodWeightMap.LoadOrStore(key, &cachedInvokers{})
cachedInvokers := cache.(*cachedInvokers)
var (
clean = false
totalWeight = int64(0)
maxCurrentWeight = int64(math.MinInt64)
now = time.Now()
selectedInvoker protocol.Invoker
selectedWeightRobin *weightedRoundRobin
)
for _, invoker := range invokers {var weight = GetWeight(invoker, invocation)
if weight < 0 {weight = 0}
identifier := invoker.GetUrl().Key()
loaded, found := cachedInvokers.LoadOrStore(identifier, &weightedRoundRobin{weight: weight})
weightRobin := loaded.(*weightedRoundRobin)
if !found {clean = true}
if weightRobin.Weight() != weight {weightRobin.setWeight(weight)
}
currentWeight := weightRobin.increaseCurrent()
weightRobin.lastUpdate = &now
if currentWeight > maxCurrentWeight {
maxCurrentWeight = currentWeight
selectedInvoker = invoker
selectedWeightRobin = weightRobin
}
totalWeight += weight
}
cleanIfRequired(clean, cachedInvokers, &now)
if selectedWeightRobin != nil {selectedWeightRobin.Current(totalWeight)
return selectedInvoker
}
// should never happen
return invokers[0]
}
- Select 办法遍历 invokers,通过 weightRobin.increaseCurrent() 作为 currentWeight,若 currentWeight 大于 maxCurrentWeight 则更新 maxCurrentWeight,设置 selectedInvoker 为以后 invoker,设置 selectedWeightRobin 为以后 weightRobin;之后对于 selectedWeightRobin 不为 nil 的执行 selectedWeightRobin.Current(totalWeight),返回 selectedInvoker
小结
roundRobinLoadBalance 的 NewRoundRobinLoadBalance 办法创立了 roundRobinLoadBalance;其 Select 办法遍历 invokers,通过 weightRobin.increaseCurrent() 作为 currentWeight,若 currentWeight 大于 maxCurrentWeight 则更新 maxCurrentWeight,设置 selectedInvoker 为以后 invoker,设置 selectedWeightRobin 为以后 weightRobin
doc
- round_robin