最近在看dubbo的一些代码,看到cluster层的负载均衡这块,目前支持一致性hash的ConsistentHashLoadBalance,
最少活跃数的LeastActiveLoadBalance,随机RandomLoadBalance,轮询的RoundRobinLoadBalance。
其中看到轮询这块有一个平滑轮询算法的算法
主要思路就是每个节点会有一个权重weight,每次让他的current = current + weight,获取最新的权重值,
同时累加每个节点的最新权重值current, totalWeight = totalWeight + current。
current值最大的节点为本次需要调用的节点,需要把本次选取节点的current = current - totalWeight。
public static void main(String[] args) {
Map<String, WeightRounbin> rounbinMap = Lists.newArrayList(
new WeightRounbin("10.0.0.1", 1),
new WeightRounbin("10.0.0.2", 2),
new WeightRounbin("10.0.0.3", 3))
.stream().collect(Collectors.toMap(WeightRounbin::getIp, x -> x));
testRound(12, rounbinMap);
}
private static void testRound(int n, Map<String, WeightRounbin> rounbinMap) {
for (int i = 0; i < n; i++) {
int MAX_WEIGHT = Integer.MIN_VALUE, totalWeight = 0;
WeightRounbin select = null;
for (WeightRounbin rounbin : rounbinMap.values()) {
int weight = rounbin.getWeight();
if (weight > MAX_WEIGHT) {
select = rounbin;
MAX_WEIGHT = weight;
}
totalWeight += weight;
}
if (select != null) {
select.resetNextWeight(totalWeight);
System.out.println(String.format("本次选择的ip: %s, 被选中次数: %s", select.getIp(), select.getCount()));
}
}
}
public static class WeightRounbin {
private String ip;
private int weight;
private AtomicInteger selectCount = new AtomicInteger(0);
private AtomicInteger current = new AtomicInteger(0);
public WeightRounbin(String ip, int weight) {
this.ip = ip;
this.weight = weight;
}
public String getIp() {
return ip;
}
public int getWeight() {
return current.addAndGet(weight);
}
public void resetNextWeight(int totalWeight) {
current.addAndGet(-totalWeight);
selectCount.incrementAndGet();
}
public int getCount() {
return selectCount.get();
}
}
调用12次的话,有6次会落到权重为3的节点,4次落到权重为2的节点,2次落到权重为1的节点。
得到的结果会穿插的,权重大的节点也不会被频繁的调用。
本次选择的ip: 10.0.0.3, 被选中次数: 1
本次选择的ip: 10.0.0.2, 被选中次数: 1
本次选择的ip: 10.0.0.3, 被选中次数: 2
本次选择的ip: 10.0.0.1, 被选中次数: 1
本次选择的ip: 10.0.0.2, 被选中次数: 2
本次选择的ip: 10.0.0.3, 被选中次数: 3
本次选择的ip: 10.0.0.3, 被选中次数: 4
本次选择的ip: 10.0.0.2, 被选中次数: 3
本次选择的ip: 10.0.0.3, 被选中次数: 5
本次选择的ip: 10.0.0.1, 被选中次数: 2
本次选择的ip: 10.0.0.2, 被选中次数: 4
本次选择的ip: 10.0.0.3, 被选中次数: 6