共计 3430 个字符,预计需要花费 9 分钟才能阅读完成。
序
本文次要钻研一下 dubbo-go 的 leastActiveLoadBalance
leastActiveLoadBalance
dubbo-go-v1.4.2/cluster/loadbalance/least_active.go
const (
// LeastActive ...
LeastActive = "leastactive"
)
func init() {extension.SetLoadbalance(LeastActive, NewLeastActiveLoadBalance)
}
type leastActiveLoadBalance struct {
}
// NewLeastActiveLoadBalance ...
func NewLeastActiveLoadBalance() cluster.LoadBalance {return &leastActiveLoadBalance{}
}
- leastActiveLoadBalance 的 NewLeastActiveLoadBalance 办法创立 leastActiveLoadBalance
Select
dubbo-go-v1.4.2/cluster/loadbalance/least_active.go
func (lb *leastActiveLoadBalance) Select(invokers []protocol.Invoker, invocation protocol.Invocation) protocol.Invoker {count := len(invokers)
if count == 0 {return nil}
if count == 1 {return invokers[0]
}
var (
leastActive int32 = -1 // The least active value of all invokers
totalWeight int64 // The number of invokers having the same least active value (LEAST_ACTIVE)
firstWeight int64 // Initial value, used for comparison
leastCount int // The number of invokers having the same least active value (LEAST_ACTIVE)
leastIndexes = make([]int, count) // The index of invokers having the same least active value (LEAST_ACTIVE)
sameWeight = true // Every invoker has the same weight value?
)
for i := 0; i < count; i++ {invoker := invokers[i]
// Active number
active := protocol.GetMethodStatus(invoker.GetUrl(), invocation.MethodName()).GetActive()
// current weight (maybe in warmUp)
weight := GetWeight(invoker, invocation)
// There are smaller active services
if leastActive == -1 || active < leastActive {
leastActive = active
leastIndexes[0] = i
leastCount = 1 // next available leastIndex offset
totalWeight = weight
firstWeight = weight
sameWeight = true
} else if active == leastActive {leastIndexes[leastCount] = i
totalWeight += weight
leastCount++
if sameWeight && (i > 0) && weight != firstWeight {sameWeight = false}
}
}
if leastCount == 1 {return invokers[0]
}
if !sameWeight && totalWeight > 0 {offsetWeight := rand.Int63n(totalWeight) + 1
for i := 0; i < leastCount; i++ {leastIndex := leastIndexes[i]
offsetWeight -= GetWeight(invokers[i], invocation)
if offsetWeight <= 0 {return invokers[leastIndex]
}
}
}
index := leastIndexes[rand.Intn(leastCount)]
return invokers[index]
}
- Select 办法遍历 invokers,挨个通过 protocol.GetMethodStatus(invoker.GetUrl(), invocation.MethodName()).GetActive() 获取 active 信息,并通过 GetWeight(invoker, invocation) 获取 weight,而后计算 leastCount、totalWeight、sameWeight;对于 leastCount 为 1 的返回 invokers[0],对于 sameWeight 为 false 且 totalWeight 大于 0 的,遍历 leastIndexes,计算 offsetWeight,若 offsetWeight 小于等于 0,则返回 invokers[leastIndex],否则通过 leastIndexes[rand.Intn(leastCount)] 计算 index,返回 invokers[index]
GetWeight
dubbo-go-v1.4.2/cluster/loadbalance/util.go
// GetWeight ...
func GetWeight(invoker protocol.Invoker, invocation protocol.Invocation) int64 {url := invoker.GetUrl()
weight := url.GetMethodParamInt64(invocation.MethodName(), constant.WEIGHT_KEY, constant.DEFAULT_WEIGHT)
if weight > 0 {
//get service register time an do warm up time
now := time.Now().Unix()
timestamp := url.GetParamInt(constant.REMOTE_TIMESTAMP_KEY, now)
if uptime := now - timestamp; uptime > 0 {warmup := url.GetParamInt(constant.WARMUP_KEY, constant.DEFAULT_WARMUP)
if uptime < warmup {if ww := float64(uptime) / float64(warmup) / float64(weight); ww < 1 {weight = 1} else if int64(ww) <= weight {weight = int64(ww)
}
}
}
}
return weight
}
- GetWeight 办法通过 url.GetMethodParamInt64(invocation.MethodName(), constant.WEIGHT_KEY, constant.DEFAULT_WEIGHT) 获取 weight,若 weight 大于 0,则计算 warmup,从新计算 weight 值
小结
leastActiveLoadBalance 的 NewLeastActiveLoadBalance 办法创立 leastActiveLoadBalance;Select 办法遍历 invokers,挨个通过 protocol.GetMethodStatus(invoker.GetUrl(), invocation.MethodName()).GetActive() 获取 active 信息,并通过 GetWeight(invoker, invocation) 获取 weight,而后计算 leastCount、totalWeight、sameWeight,最初计算 index
doc
- least_active
正文完