protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
//invokers及weights的映射关系通过数组顺序
// the size of machine
int length = invokers.size();
int totalWeight = 0;
// Every invoker has the same weigh
boolean sameWeight = true;
int offset;
int i;
for(offset = 0; offset < length; ++offset) {
//get the weight of every machine
i = this.getWeight((Invoker)invokers.get(offset), invocation);
// accumulate the totalWeight from every machine
totalWeight += i;
// if current sameWeight is true and the weight of current machine is not equal with the prev machine
// then mark the variable of sameWeight is false;
if (sameWeight && offset > 0 && i != this.getWeight((Invoker)invokers.get(offset - 1), invocation)) {
sameWeight = false;
}
}
// if totalWeight is large than zero and sameWeight is false,
if (totalWeight > 0 && !sameWeight) {
//select a number from totalWeight;
offset = this.random.nextInt(totalWeight);
for(i = 0; i < length; ++i) {
// mark plus operation
offset -= this.getWeight((Invoker)invokers.get(i), invocation);
if (offset < 0) {
return (Invoker)invokers.get(i);
}
}
}
return (Invoker)invokers.get(this.random.nextInt(length));
}
protected int getWeight(Invoker<?> invoker, Invocation invocation) {
int weight = invoker.getUrl().getMethodParameter(invocation.getMethodName(), "weight", 100);
if (weight > 0) {
//开始运行参数
long timestamp = invoker.getUrl().getParameter("timestamp", 0L);
if (timestamp > 0L) {
// 程序启动到现在的历时计算。 一个服务运行的时间越长,也就越稳定,那对应的权重也就越高。
int uptime = (int)(System.currentTimeMillis() - timestamp);
// 预热时间 一个系统从启动到完美运行,是需要一段时间的,也就是这个预热时间。
//所以在这里预热时间段内的请求,是不能完全根据设置的权重值来进行负载的,需要进行一下预热程度的计算。这样就能够保证系统在真正的完美运行时间,不会处理太多的请求
int warmup = invoker.getUrl().getParameter("warmup", 600000); // 完美运行10分钟
//在运行时间大于0,也就是已经启动了,然后运行时间小于预热时间的,会进行权重的计算。
//这里是Dubbo针对系统契合环境做的一些优化,因为一个系统从启动到完美运行,是需要一段时间的,也就是这个预热时间。
//所以在这里预热时间段内的请求,是不能完全根据设//置的权重值来进行负载的,需要进行一下预热程度的计算。
//这样就能够保证系统在真正的完美运行时间,不会处理太多的请求 所以这里返回 低于默认100的权重 避免在完美运行时间前被调用
if (uptime > 0 && uptime < warmup) {
weight = calculateWarmupWeight(uptime, warmup, weight);
}
}
}
return weight;
}
//根据预热时间与程序启动到现在的历时计算权重比例 warmup 预热时间。uptime 程序启动到现在的历时计算。5min ,10min,100
static int calculateWarmupWeight(int uptime, int warmup, int weight) {
int ww = (int)((float)uptime / ((float)warmup / (float)weight)); // 5.0/(10.0/100.0)=50
return ww < 1 ? 1 : (ww > weight ? weight : ww); // 50
}