Skip to content

Commit

Permalink
[type:feat] use binary search optimize random load balance
Browse files Browse the repository at this point in the history
  • Loading branch information
eye committed Aug 3, 2023
1 parent 4271cb8 commit b5e6678
Showing 1 changed file with 19 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package org.apache.shenyu.loadbalancer.spi;

import java.security.SecureRandom;
import java.util.Arrays;
import java.util.List;
import org.apache.shenyu.loadbalancer.entity.Upstream;
import org.apache.shenyu.spi.Join;
Expand All @@ -41,42 +42,41 @@ public Upstream doSelect(final List<Upstream> upstreamList, final String ip) {
weights[0] = firstUpstreamWeight;
// init the totalWeight
int totalWeight = firstUpstreamWeight;
int halfLengthTotalWeight = 0;
for (int i = 1; i < length; i++) {
int currentUpstreamWeight = getWeight(upstreamList.get(i));
if (i <= (length + 1) / 2) {
halfLengthTotalWeight = totalWeight;
}
weights[i] = currentUpstreamWeight;
totalWeight += currentUpstreamWeight;
weights[i] = totalWeight;
if (sameWeight && currentUpstreamWeight != firstUpstreamWeight) {
// Calculate whether the weight of ownership is the same.
sameWeight = false;
}
}
if (totalWeight > 0 && !sameWeight) {
return random(totalWeight, halfLengthTotalWeight, weights, upstreamList);
return random(totalWeight, weights, upstreamList, length);
}
return random(upstreamList);
}

private Upstream random(final int totalWeight, final int halfLengthTotalWeight, final int[] weights, final List<Upstream> upstreamList) {
private Upstream random(final int totalWeight, final int[] weights, final List<Upstream> upstreamList, final int length) {
// If the weights are not the same and the weights are greater than 0, then random by the total number of weights.
int offset = RANDOM.nextInt(totalWeight);
int index = 0;
int end = weights.length;
if (offset >= halfLengthTotalWeight) {
index = (weights.length + 1) / 2;
offset -= halfLengthTotalWeight;
if (length <= 4) {
for (int i = 0; i < length; i++) {
if (offset < weights[i]) {
return upstreamList.get(i);
}
}
} else {
end = (weights.length + 1) / 2;
}
// Determine which segment the random value falls on
for (; index < end; index++) {
offset -= weights[index];
if (offset < 0) {
return upstreamList.get(index);
int i = Arrays.binarySearch(weights, offset);
if (i < 0) {
i = -i - 1;
} else {
while (weights[i + 1] == offset) {
i++;
}
i++;
}
return upstreamList.get(i);
}
return random(upstreamList);
}
Expand Down

0 comments on commit b5e6678

Please sign in to comment.