乐趣区

关于dubbo:聊聊dubbogo的roundRobinLoadBalance

本文次要钻研一下 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
退出移动版