Skip to content

xds: add weighted round robin LB policy support #9873

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 30 commits into from
Feb 27, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
1f7bbd8
refactor round robin LB
YifeiZhuang Jan 23, 2023
73cf208
rename abstract*
YifeiZhuang Jan 25, 2023
12e7928
refactor round robin LB
YifeiZhuang Jan 23, 2023
2727d9b
rename abstract*
YifeiZhuang Jan 25, 2023
764c9a9
temp: add weightedroundrobinimpl
YifeiZhuang Jan 25, 2023
afa10fb
add weighted round robin picker and scheduler
YifeiZhuang Feb 2, 2023
d4f785d
comments, and add afterSubchannelUpdate
YifeiZhuang Feb 3, 2023
60af73c
format
YifeiZhuang Feb 3, 2023
4228f97
move abstraction to composition
YifeiZhuang Feb 3, 2023
cf3d640
remove listener
YifeiZhuang Feb 3, 2023
c7bcfcd
add update timer to LB , not in picker
YifeiZhuang Feb 4, 2023
975eeed
use original round robin wl
YifeiZhuang Feb 6, 2023
5300199
add subchannel listener
YifeiZhuang Feb 6, 2023
2458ac9
add test
YifeiZhuang Feb 7, 2023
9cd33b6
Merge branch 'master' of https://github.com/grpc/grpc-java into wrr-impl
YifeiZhuang Feb 8, 2023
23231eb
add more tests
YifeiZhuang Feb 8, 2023
3d51405
add provider test
YifeiZhuang Feb 9, 2023
e6886c1
fix current picker
YifeiZhuang Feb 9, 2023
3da127e
remove virtual time, change comment
YifeiZhuang Feb 10, 2023
cb31730
fix avg weight
YifeiZhuang Feb 13, 2023
01a7d1a
Merge branch 'master' of https://github.com/grpc/grpc-java into wrr-impl
YifeiZhuang Feb 13, 2023
6e496da
Merge branch 'master' of https://github.com/grpc/grpc-java into wrr-impl
YifeiZhuang Feb 14, 2023
6dfa072
add env variable
YifeiZhuang Feb 16, 2023
f786098
Merge branch 'master' of https://github.com/grpc/grpc-java into wrr-impl
YifeiZhuang Feb 16, 2023
0bdce32
parse wrr proto
YifeiZhuang Feb 17, 2023
3979ef8
add test scheduler
YifeiZhuang Feb 23, 2023
0704a69
fix comments, timer, volatile, etc
YifeiZhuang Feb 23, 2023
fc0d3dd
bazel checksum, and use ticker
YifeiZhuang Feb 24, 2023
f728281
infTime = nanoTime() + MAX_VALUE
YifeiZhuang Feb 24, 2023
1ef6221
minor fix
YifeiZhuang Feb 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
add more tests
  • Loading branch information
YifeiZhuang committed Feb 9, 2023
commit 23231ebb4b88aa0b716a5df594f6f39f7e384bdf
3 changes: 1 addition & 2 deletions core/src/main/java/io/grpc/util/RoundRobinLoadBalancer.java
Original file line number Diff line number Diff line change
Expand Up @@ -336,8 +336,7 @@ public boolean isEquivalentTo(RoundRobinPicker picker) {
}
}

@VisibleForTesting
static final class EmptyPicker extends RoundRobinPicker {
public static final class EmptyPicker extends RoundRobinPicker {

private final Status status;

Expand Down
37 changes: 24 additions & 13 deletions xds/src/main/java/io/grpc/xds/WeightedRoundRobinLoadBalancer.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import io.grpc.EquivalentAddressGroup;
import io.grpc.LoadBalancer;
import io.grpc.NameResolver;
import io.grpc.Status;
import io.grpc.SynchronizationContext;
import io.grpc.SynchronizationContext.ScheduledHandle;
import io.grpc.internal.TimeProvider;
Expand Down Expand Up @@ -66,8 +67,15 @@ final class WeightedRoundRobinLoadBalancer extends RoundRobinLoadBalancer {

@Override
public boolean acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {
if (resolvedAddresses.getLoadBalancingPolicyConfig() == null) {
handleNameResolutionError(Status.UNAVAILABLE.withDescription(
"NameResolver returned no WeightedRoundRobinLoadBalancerConfig. addrs="
+ resolvedAddresses.getAddresses()
+ ", attrs=" + resolvedAddresses.getAttributes()));
return false;
}
config =
(WeightedRoundRobinLoadBalancerConfig) resolvedAddresses.getLoadBalancingPolicyConfig();
(WeightedRoundRobinLoadBalancerConfig) resolvedAddresses.getLoadBalancingPolicyConfig();
boolean accepted = super.acceptResolvedAddresses(resolvedAddresses);
new UpdateWeightTask().run();
afterSubchannelUpdate();
Expand Down Expand Up @@ -138,6 +146,7 @@ public Subchannel createSubchannel(CreateSubchannelArgs args) {
}
}

@VisibleForTesting
static final class WrrSubchannel extends ForwardingSubchannel {
private final Subchannel delegate;

Expand Down Expand Up @@ -210,7 +219,7 @@ protected Subchannel delegate() {
final class WeightedRoundRobinPicker extends ReadyPicker {
private final List<Subchannel> list;
private final AtomicReference<EdfScheduler> schedulerRef;
volatile boolean rrMode = false;
private volatile boolean rrMode = false;

WeightedRoundRobinPicker(List<Subchannel> list, int startIndex) {
super(list, startIndex);
Expand All @@ -227,7 +236,7 @@ public PickResult pickSubchannel(PickSubchannelArgs args) {
}
int pickIndex = schedulerRef.get().pick();
WrrSubchannel subchannel = (WrrSubchannel) list.get(pickIndex);
if (config.enableOobLoadReport) {
if (!config.enableOobLoadReport) {
return PickResult.withSubchannel(
subchannel,
OrcaPerRequestUtil.getInstance().newOrcaClientStreamTracerFactory(
Expand Down Expand Up @@ -284,12 +293,12 @@ public boolean isEquivalentTo(RoundRobinPicker picker) {
}

/**
* An earliest deadline first implementation in which each object is
* The earliest deadline first implementation in which each object is
* chosen deterministically and periodically with frequency proportional to its weight.
*
* <p>Specifically, each object added to chooser is given a period equal to the multiplicative
* inverse of its weight. The place of each object in its period is tracked, and each call to
* choose returns the child with the least remaining time in its period (1/weight).
* choose returns the object with the least remaining time in its period (1/weight).
* (Ties are broken by the order in which the children were added to the chooser.)
* For example, if items A and B are added
* with weights 0.5 and 0.2, successive chooses return:
Expand Down Expand Up @@ -328,8 +337,6 @@ private static final class EdfScheduler {

/**
* Upon every pick() the "virtual time" is advanced closer to the period of next items.
* In the WeightedRoundRobinChooser implementation this is done by subtracting the period of the
* picked object from all other items yielding O(n).
* Here we have an explicit "virtualTimeNow", which will be added to the period of all newly
* scheduled objects (virtualTimeNow + period).
*/
Expand Down Expand Up @@ -364,7 +371,7 @@ private static final class EdfScheduler {
* @param index The field {@link ObjectState#index} to be added/updated
* @param weight positive weight for the added/updated object
*/
public void add(int index, double weight) {
void add(int index, double weight) {
checkArgument(weight > 0.0, "Weights need to be positive.");
ObjectState state = new ObjectState(Math.max(weight, MINIMUM_WEIGHT), index);
state.deadline = virtualTimeNow + 1 / state.weight;
Expand All @@ -373,11 +380,8 @@ public void add(int index, double weight) {

/**
* Picks the next WRR object.
* Concurrent pick() has issue:
*
* @return next object index from WRR, -1 if empty;
*/
public int pick() {
int pick() {
synchronized (lock) {
ObjectState minObject = prioQueue.remove();
// Simulate advancing in time by setting the current time to the period of the nearest item
Expand Down Expand Up @@ -410,6 +414,9 @@ static final class WeightedRoundRobinLoadBalancerConfig {
final Long oobReportingPeriodNanos;
final Long weightUpdatePeriodNanos;

public static Builder newBuilder() {
return new Builder();
}

private WeightedRoundRobinLoadBalancerConfig(Long blackoutPeriodNanos,
Long weightExpirationPeriodNanos,
Expand All @@ -423,13 +430,17 @@ private WeightedRoundRobinLoadBalancerConfig(Long blackoutPeriodNanos,
this.weightUpdatePeriodNanos = weightUpdatePeriodNanos;
}

static class Builder {
static final class Builder {
Long blackoutPeriodNanos = 10_000_000_000L; // 10s
Long weightExpirationPeriodNanos = 180_000_000_000L; //3min
Boolean enableOobLoadReport = false;
Long oobReportingPeriodNanos = 10_000_000_000L; // 10s
Long weightUpdatePeriodNanos = 100_000_000L; // 1s

private Builder() {

}

Builder setBlackoutPeriodNanos(Long blackoutPeriodNanos) {
checkArgument(blackoutPeriodNanos != null);
this.blackoutPeriodNanos = blackoutPeriodNanos;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,19 @@ public ConfigOrError parseLoadBalancingPolicyConfig(Map<String, ?> rawConfig) {
Long weightUpdatePeriodNanos = JsonUtil.getStringAsDuration(rawConfig, "weightUpdatePeriod");

WeightedRoundRobinLoadBalancerConfig.Builder configBuilder =
new WeightedRoundRobinLoadBalancerConfig.Builder();
WeightedRoundRobinLoadBalancerConfig.newBuilder();
if (blackoutPeriodNanos != null) {
configBuilder.setBlackoutPeriodNanos(blackoutPeriodNanos);
}
if (weightExpirationPeriodNanos != null) {
configBuilder.setWeightExpirationPeriodNanos(weightExpirationPeriodNanos);
}
if (oobReportingPeriodNanos != null) {
if (enableOobLoadReport != null) {
configBuilder.setEnableOobLoadReport(enableOobLoadReport);
}
if (oobReportingPeriodNanos != null) {
configBuilder.setOobReportingPeriodNanos(oobReportingPeriodNanos);
}
if (weightUpdatePeriodNanos != null) {
configBuilder.setWeightUpdatePeriodNanos(weightUpdatePeriodNanos);
if (weightUpdatePeriodNanos < MIN_WEIGHT_UPDATE_PERIOD_NANOS) {
Expand Down
Loading