在集群负载均衡时,Dubbo提供了4种均衡策略,如:Random LoadBalance(随机均衡算法)、;RoundRobin LoadBalance(权重轮循均衡算法)、LeastAction LoadBalance(最少活跃调用数均衡算法)、ConsistentHash LoadBalance(一致性Hash均衡算法)。缺省时为Random随机调用。具体UML类图如下:
protected Invoker doSelect(List> invokers, URL url, Invocation invocation) {
int length = invokers.size();// 总个数
int totalWeight = 0;// 总权重
boolean sameWeight = true;// 权重是否都一样
int offset;
int i;
for(offset = 0; offset < length; ++offset) {
i = this.getWeight((Invoker)invokers.get(offset), invocation);
totalWeight += i;// 累计总权重
if(sameWeight && offset > 0 && i != this.getWeight((Invoker)invokers.get(offset - 1), invocation)) {// 计算所有权重是否一样
sameWeight = false;
}
}
if(totalWeight > 0 && !sameWeight) {
// 如果权重不相同且权重大于0则按总权重数随机
offset = this.random.nextInt(totalWeight);
// 并确定随机值落在哪个片断上
for(i = 0; i < length; ++i) {
offset -= this.getWeight((Invoker)invokers.get(i), invocation);
if(offset < 0) {
return (Invoker)invokers.get(i);
}
}
}
// 如果权重相同或权重为0则均等随机
return (Invoker)invokers.get(this.random.nextInt(length));
}
protected Invoker doSelect(List> invokers, URL url, Invocation invocation) {
String key = ((Invoker)((List)invokers).get(0)).getUrl().getServiceKey() + "." + invocation.getMethodName();
int length = ((List)invokers).size();// 总个数
int maxWeight = 0;// 最大权重
int minWeight = 2147483647;// 最小权重
int currentWeight;
for(int sequence = 0; sequence < length; ++sequence) {
currentWeight = this.getWeight((Invoker)((List)invokers).get(sequence), invocation);
maxWeight = Math.max(maxWeight, currentWeight);// 累计最大权重
minWeight = Math.min(minWeight, currentWeight);// 累计最小权重
}
AtomicPositiveInteger var13;
if(maxWeight > 0 && minWeight < maxWeight) { // 权重不一样
var13 = (AtomicPositiveInteger)this.weightSequences.get(key);
if(var13 == null) {
this.weightSequences.putIfAbsent(key, new AtomicPositiveInteger());
var13 = (AtomicPositiveInteger)this.weightSequences.get(key);
}
currentWeight = var13.getAndIncrement() % maxWeight;
ArrayList weightInvokers = new ArrayList();
Iterator weightLength = ((List)invokers).iterator();
while(weightLength.hasNext()) {
Invoker invoker = (Invoker)weightLength.next();
if(this.getWeight(invoker, invocation) > currentWeight) { // 筛选权重大于当前权重基数的Invoker
weightInvokers.add(invoker);
}
}
int var14 = weightInvokers.size();
if(var14 == 1) {
return (Invoker)weightInvokers.get(0);
}
if(var14 > 1) {
invokers = weightInvokers;
length = weightInvokers.size();
}
}
var13 = (AtomicPositiveInteger)this.sequences.get(key);
if(var13 == null) {
this.sequences.putIfAbsent(key, new AtomicPositiveInteger());
var13 = (AtomicPositiveInteger)this.sequences.get(key);
}
// 取模轮循
return (Invoker)((List)invokers).get(var13.getAndIncrement() % length);
}
protected Invoker doSelect(List> invokers, URL url, Invocation invocation) {
int length = invokers.size();//总活跃数
int leastActive = -1;//初始化最小活跃数
int leastCount = 0;//最少活跃数相同数量
int[] leastIndexs = new int[length];//最少活跃数相同的数据
int totalWeight = 0;//总权重
int firstWeight = 0;//第一个权重方便对比
boolean sameWeight = true;//是否所有权重相同
int offsetWeight;
int leastIndex;
for(offsetWeight = 0; offsetWeight < length; ++offsetWeight) {
Invoker i = (Invoker)invokers.get(offsetWeight);
leastIndex = RpcStatus.getStatus(i.getUrl(), invocation.getMethodName()).getActive();
int weight = i.getUrl().getMethodParameter(invocation.getMethodName(), "weight", 100);// 权重
if(leastActive != -1 && leastIndex >= leastActive) { // 发现更小的活跃数,重新开始
if(leastIndex == leastActive) {
leastIndexs[leastCount++] = offsetWeight;// 累计相同最小活跃数下标
totalWeight += weight;// 累计总权重
if(sameWeight && offsetWeight > 0 && weight != firstWeight) { // 判断所有权重是否一样
sameWeight = false;
}
}
} else {
leastActive = leastIndex;// 记录最小活跃数
leastCount = 1;// 重新统计相同最小活跃数的个数
leastIndexs[0] = offsetWeight;// 重新记录最小活跃数下标
totalWeight = weight;// 重新累计总权重
firstWeight = weight;// 记录第一个权重
sameWeight = true;// 还原权重相同标识
}
}
if(leastCount == 1) { // 如果只有一个最小则直接返回
return (Invoker)invokers.get(leastIndexs[0]);
} else {
if(!sameWeight && totalWeight > 0) {
// 如果权重不相同且权重大于0则按总权重数随机
offsetWeight = this.random.nextInt(totalWeight);
// 并确定随机值落在哪个片断上
for(int var15 = 0; var15 < leastCount; ++var15) {
leastIndex = leastIndexs[var15];
offsetWeight -= this.getWeight((Invoker)invokers.get(leastIndex), invocation);
if(offsetWeight <= 0) {
return (Invoker)invokers.get(leastIndex);
}
}
}
// 如果权重相同或权重为0则均等随机
return (Invoker)invokers.get(leastIndexs[this.random.nextInt(leastCount)]);
}
}