前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >聊聊dubbo-go的leastActiveLoadBalance

聊聊dubbo-go的leastActiveLoadBalance

原创
作者头像
code4it
修改2020-08-12 10:01:46
3100
修改2020-08-12 10:01:46
举报
文章被收录于专栏:码匠的流水账码匠的流水账

本文主要研究一下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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • leastActiveLoadBalance
  • Select
  • GetWeight
  • 小结
  • doc
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档