本文次要钻研一下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