protected<T>Invoker<T>doSelect(List<Invoker<T>> invokers,URL url,Invocation invocation){int length = invokers.size();
所有调用者中最小活跃数
int leastActive =-1;
最小活跃数相同的Invoker数量
int leastCount =0;int[] leastIndexes =newint[length];int[] weights =newint[length];
所有最不活跃的调用者的预热权重的总和
int totalWeight =0;
第一个最不活跃的调用者的权重
int firstWeight =0;boolean sameWeight =true;
根据Invoker的活跃数计算最小活跃数
for(int i =0; i < length; i++){Invoker<T> invoker = invokers.get(i);
获取当前url下的方法对应的活跃数,活跃数通过filter机制设置
int active =RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName()).getActive();
默认权重100,当启动时间小于预热时间[启动时间/预热时间]*100int afterWarmup =getWeight(invoker, invocation);
每个Invoker的权重
weights[i]= afterWarmup;if(leastActive ==-1|| active < leastActive){
第一个Invoker的最小权重或者出现新的最小权重Invoker
leastActive = active;// Reset the number of least active invokers
leastCount =1;// Put the first least active invoker first in leastIndexes
leastIndexes[0]= i;// Reset totalWeight
totalWeight = afterWarmup;// Record the weight the first least active invoker
firstWeight = afterWarmup;
sameWeight =true;}elseif(active == leastActive){
出现最小活跃数和已经统计的最小活跃数相同
leastIndexes[leastCount++]= i;
累计总权重
totalWeight += afterWarmup;
存在权重不同 则使用step-2 b 加权随机
if(sameWeight && afterWarmup != firstWeight){
sameWeight =false;}}}
step-2: 获取Invoker
a 最小权重的Invoker数量相同的只有一个
if(leastCount ==1){return invokers.get(leastIndexes[0]);}
b 最小权重的Invoker数量相同有多个 并且权重不相同
if(!sameWeight && totalWeight >0){
随机一个值
int offsetWeight =ThreadLocalRandom.current().nextInt(totalWeight);for(int i =0; i < leastCount; i++){int leastIndex = leastIndexes[i];
判断随机的权重在不在当前加权权重范围
offsetWeight -= weights[leastIndex];if(offsetWeight <0){return invokers.get(leastIndex);}}}
c 权重全部相同或者总权重为0,直接随机获取
return invokers.get(leastIndexes[ThreadLocalRandom.current().nextInt(leastCount)]);}