策略:RandomLoadBalance,RoundRobinLoadBalance,ConsistentHashLoadBalance,LeastActiveLoadBalance
======= LoadBalance ======
Invokerselect(List> invokers, URL url, Invocation invocation)
======== AbstractLoadBalance =======
weight: 权重,默认是100,
uptime:invoker运行时间 = 当前系统时间 - invoker运行时间
warmup:invoker预热时间,默认是10 * 60 * 1000 = 10min
uptime>0 && uptime < warmup => calculateWarmupWeight
即当invoker运行时间小于10min,则需要计算权重,运行时间大于10min,权重直接是默认100
protected int getWeight(Invoker?invoker, Invocation invocation) {
int weight = invoker.getUrl().getMethodParameter(invocation.getMethodName(), Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT);
if (weight > 0) { long timestamp = invoker.getUrl().getParameter(Constants.TIMESTAMP_KEY, 0L); if (timestamp > 0L) { int uptime = (int) (System.currentTimeMillis() - timestamp); int warmup = invoker.getUrl().getParameter(Constants.WARMUP_KEY, Constants.DEFAULT_WARMUP); if (uptime > 0 && uptime < warmup) { weight = calculateWarmupWeight(uptime, warmup, weight); } } } return weight;}
//计算权重
计算规则很简单:uptime/(warmup/weight) = (uptime/warmup) * weight,运行时间/默认预热时间 * 100也就是说当invoker运行时间小于10min时,invoker的运行时间越长,其权重越高static int calculateWarmupWeight(int uptime, int warmup, int weight) { int ww = (int) ( (float) uptime / ( (float) warmup / (float) weight ) ); return ww < 1 ? 1 : (ww > weight ? weight : ww);}
======= RandomLoadBalance ======
选择算法,也比较简单//若权重都一样,则随机选择其中一个invoker//若权重不一样,则在0 - totalWeight 中生成一个随机数,判断落在哪个片段示意图:权重:invoker0=100,invoker1=90,invoker2=80,invoker3=70,则totalWeight=100+90+80+70=340转换成图表,0-100 区段属于invoker0,100-190属于invoker1 ..若生成随机数random=260,属于2区段,则选中invoker2 protectedInvokerdoSelect(List> invokers, URL url, Invocation invocation) {
int length = invokers.size(); // 总个数
int totalWeight = 0; // 总权重
boolean sameWeight = true; // 权重是否都一样
for (int i = 0; i < length; i++) {
int weight = getWeight(invokers.get(i), invocation);
totalWeight += weight; // 累计总权重
if (sameWeight && i > 0
&& weight != getWeight(invokers.get(i - 1), invocation)) {
sameWeight = false; // 计算所有权重是否一样
}
}
if (totalWeight > 0 && ! sameWeight) {
// 如果权重不相同且权重大于0则按总权重数随机
int offset = random.nextInt(totalWeight);
// 并确定随机值落在哪个片断上
for (int i = 0; i < length; i++) {
offset -= getWeight(invokers.get(i), invocation);
if (offset < 0) {
return invokers.get(i);
}
}
}
// 如果权重相同或权重为0则均等随机
return invokers.get(random.nextInt(length));
}