背景
在集群负载均衡时,Dubbo 提供了多种均衡策略,缺省为 weighted random
基于权重的随机负载均衡策略。并且,默认权重相同。当权重相同和不同时,随机逻辑不同。这样就需要判断权重是否相同。
权重不同
假设集群中存在四个服务a、b、c、d,权重分别为10、20、25、15。随机逻辑如下:
- 通过加和算出总权重,总权重为10+20+25+15=70。
- 基于总权重生成随机数,随机数需满足0<=randomValue<70。
- 按序排列得出各个服务对应区间,服务a,b,c,d对应区间分别为[0, 10),[10, 30),[30, 55),[55, 70)。
- 判断随机数在哪个区间,就负载到对应的服务。
代码逻辑如下:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class LoadBalanceDemo {
public static void main(String[] args) {
List<Serv> l = new ArrayList<>(4);
Serv a = new Serv("a", 10);
l.add(a);
Serv b = new Serv("b", 20);
l.add(b);
Serv c = new Serv("c", 25);
l.add(c);
Serv d = new Serv("d", 15);
l.add(d);
Serv res = null;
int totalWeight = 0;
int[] weights = new int[4];
for (int i = 0; i < l.size(); i++) {
Serv serv = l.get(i);
totalWeight += serv.weight;
weights[i] = totalWeight;
}
Random random = new Random();
int randomVal = random.nextInt(totalWeight);
for (int i = 0; i < weights.length; i++) {
int weight = weights[i];
if (randomVal < weight) {
res = l.get(i);
}
}
System.out.println(res.name);
}
static class Serv {
String name;
int weight;
public Serv(String name, int weight) {
this.name = name;
this.weight = weight;
}
}
}
权重相同
权重相同时,只需要按照服务个数进行随机即可。代码逻辑如下:
int randomVal = new Random().nextInt(servs.size());
重头戏
如何判断权重是否相同呢?
方法一:获取任一服务的权重与其他服务权重一一作比较。如果有不同的,那权重一定不同。否则则权重相同。代码逻辑如下
public static void main(String[] args) {
List<Serv> l = new ArrayList<>(4);
Serv a = new Serv("a", 10);
l.add(a);
Serv b = new Serv("b", 20);
l.add(b);
Serv c = new Serv("c", 25);
l.add(c);
Serv d = new Serv("d", 15);
l.add(d);
boolean sameWeight = true;
Serv baseServ = l.get(0);
for (int i = 1; i < l.size(); i++) {
Serv serv = l.get(i);
if (baseServ.weight != serv.weight) {
sameWeight = false;
}
}
System.out.println(sameWeight);
}
这种方法的优点是直观,缺点是存在硬编码。
方法二:按序判断单一权重和总权重的倍数关系。因为我们是通过加和的方式算出总权重,当权重相同时,那第一个服务的权重就等于当前累加值,第二个服务的权重等于当前累加值的二分之一,以此类推。这样,我们就能判断权重是否相同了。代码逻辑如下:
public static void main(String[] args) {
List<Serv> l = new ArrayList<>(4);
Serv a = new Serv("a", 10);
l.add(a);
Serv b = new Serv("b", 20);
l.add(b);
Serv c = new Serv("c", 25);
l.add(c);
Serv d = new Serv("d", 15);
l.add(d);
boolean sameWeight = true;
int totalWeight = 0;
for (int i = 0; i < l.size(); i++) {
Serv serv = l.get(i);
if (serv.weight * i != totalWeight) {
sameWeight = false;
}
totalWeight += serv.weight;
}
System.out.println(sameWeight);
}