RoundRobin LoadBalance
- 轮循,按公约后的权重设置轮循比率。
- 存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。
1)获取轮询key 服务名+方法名
获取可供调用的invokers个数length
设置最大权重的默认值maxWeight=0
设置最小权重的默认值minWeight=Integer.MAX_VALUE
2)遍历所有Inokers,比较出得出maxWeight和minWeight
3)如果权重是不一样的
根据key获取自增序列
自增序列加一与最大权重取模默认得到currentWeigth
遍历所有invokers筛选出大于currentWeight的invokers
设置可供调用的invokers的个数length
4)自增序列加一并与length取模,从invokers获取invoker
public class RoundRobinLoadBalance extends AbstractLoadBalance {
public static final String NAME = "roundrobin";
private final ConcurrentMap<String, AtomicPositiveInteger> sequences = new ConcurrentHashMap<String, AtomicPositiveInteger>();
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName();
int length = invokers.size(); // Number of invokers
int maxWeight = 0; // The maximum weight 最大权重值
int minWeight = Integer.MAX_VALUE; // The minimum weight 最小权重支持,默认最大
final LinkedHashMap<Invoker<T>, IntegerWrapper> invokerToWeightMap = new LinkedHashMap<Invoker<T>, IntegerWrapper>();
//权重值总数
int weightSum = 0;
for (int i = 0; i < length; i++) {
//获取权重值
int weight = getWeight(invokers.get(i), invocation);
//获取最大和最小权重值
maxWeight = Math.max(maxWeight, weight); // Choose the maximum weight
minWeight = Math.min(minWeight, weight); // Choose the minimum weight
if (weight > 0) {
invokerToWeightMap.put(invokers.get(i), new IntegerWrapper(weight));
weightSum += weight;
}
}
AtomicPositiveInteger sequence = sequences.get(key);
if (sequence == null) {
sequences.putIfAbsent(key, new AtomicPositiveInteger());
sequence = sequences.get(key);
}
int currentSequence = sequence.getAndIncrement();
if (maxWeight > 0 && minWeight < maxWeight) {
//轮询当前值
int mod = currentSequence % weightSum;
for (int i = 0; i < maxWeight; i++) {
//轮询当前值的余数轮询从服务中获取
for (Map.Entry<Invoker<T>, IntegerWrapper> each : invokerToWeightMap.entrySet()) {
final Invoker<T> k = each.getKey();
final IntegerWrapper v = each.getValue();
if (mod == 0 && v.getValue() > 0) {
return k;
}
if (v.getValue() > 0) {
v.decrement();
mod--;
}
}
}
}
// Round robin
//直接轮询找服务
return invokers.get(currentSequence % length);
}
private static final class IntegerWrapper {
private int value;
public IntegerWrapper(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public void decrement() {
this.value--;
}
}
}