in shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/ShortestResponseLoadBalancer.java [34:82]
protected Upstream doSelect(final List<Upstream> upstreamList, final String ip) {
int length = upstreamList.size();
long shortestResponse = Long.MAX_VALUE;
int shortestCount = 0;
int[] shortestIndexes = new int[length];
int[] weights = new int[length];
int totalWeight = 0;
int firstWeight = 0;
boolean sameWeight = true;
for (int i = 0; i < upstreamList.size(); i++) {
Upstream upstream = upstreamList.get(i);
AtomicLong inflight = upstream.getInflight();
// Calculate the estimated response time from the product of active connections and succeeded average elapsed time.
long estimateResponse = upstream.getSucceededAverageElapsed() * inflight.get();
int afterWarmup = getWeight(upstream);
weights[i] = afterWarmup;
if (estimateResponse < shortestResponse) {
shortestResponse = estimateResponse;
shortestCount = 1;
shortestIndexes[0] = i;
totalWeight = afterWarmup;
firstWeight = afterWarmup;
sameWeight = true;
} else if (estimateResponse == shortestResponse) {
shortestIndexes[shortestCount++] = i;
totalWeight += afterWarmup;
if (sameWeight && i > 0
&& afterWarmup != firstWeight) {
sameWeight = false;
}
}
}
if (shortestCount == 1) {
return upstreamList.get(shortestIndexes[0]);
}
if (!sameWeight && totalWeight > 0) {
int offsetWeight = ThreadLocalRandom.current().nextInt(totalWeight);
for (int i = 0; i < shortestCount; i++) {
int shortestIndex = shortestIndexes[i];
offsetWeight -= weights[shortestIndex];
if (offsetWeight < 0) {
return upstreamList.get(shortestIndex);
}
}
}
return upstreamList.get(shortestIndexes[ThreadLocalRandom.current().nextInt(shortestCount)]);
}