Skip to content

Commit dc83446

Browse files
committed
xds: Stop extending RR in WRR
They share very little code, and we really don't want RoundRobinLb to be public and non-final. Originally, WRR was expected to share much more code with RR, and even delegated to RR at times. The delegation was removed in 111ff60. After dca89b2, most of the sharing has been moved out into general-purpose tools that can be used by any LB policy. FixedResultPicker now has equals to makes it as a EmptyPicker replacement. RoundRobinLb still uses EmptyPicker because fixing its tests is a larger change. OutlierDetectionLbTest was changed because FixedResultPicker is used by PickFirstLeafLb, and now RoundRobinLb can squelch some of its updates for ready pickers.
1 parent 0090a52 commit dc83446

File tree

5 files changed

+63
-12
lines changed

5 files changed

+63
-12
lines changed

api/src/main/java/io/grpc/LoadBalancer.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,5 +1526,19 @@ public PickResult pickSubchannel(PickSubchannelArgs args) {
15261526
public String toString() {
15271527
return "FixedResultPicker(" + result + ")";
15281528
}
1529+
1530+
@Override
1531+
public int hashCode() {
1532+
return result.hashCode();
1533+
}
1534+
1535+
@Override
1536+
public boolean equals(Object o) {
1537+
if (!(o instanceof FixedResultPicker)) {
1538+
return false;
1539+
}
1540+
FixedResultPicker that = (FixedResultPicker) o;
1541+
return this.result.equals(that.result);
1542+
}
15291543
}
15301544
}

util/src/main/java/io/grpc/util/RoundRobinLoadBalancer.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import com.google.common.base.Preconditions;
2828
import io.grpc.ConnectivityState;
2929
import io.grpc.EquivalentAddressGroup;
30-
import io.grpc.Internal;
3130
import io.grpc.LoadBalancer;
3231
import io.grpc.NameResolver;
3332
import java.util.ArrayList;
@@ -41,10 +40,9 @@
4140
* A {@link LoadBalancer} that provides round-robin load-balancing over the {@link
4241
* EquivalentAddressGroup}s from the {@link NameResolver}.
4342
*/
44-
@Internal
45-
public class RoundRobinLoadBalancer extends MultiChildLoadBalancer {
43+
final class RoundRobinLoadBalancer extends MultiChildLoadBalancer {
4644
private final AtomicInteger sequence = new AtomicInteger(new Random().nextInt());
47-
protected SubchannelPicker currentPicker = new EmptyPicker();
45+
private SubchannelPicker currentPicker = new EmptyPicker();
4846

4947
public RoundRobinLoadBalancer(Helper helper) {
5048
super(helper);
@@ -87,7 +85,7 @@ private void updateBalancingState(ConnectivityState state, SubchannelPicker pick
8785
}
8886
}
8987

90-
protected SubchannelPicker createReadyPicker(Collection<ChildLbState> children) {
88+
private SubchannelPicker createReadyPicker(Collection<ChildLbState> children) {
9189
List<SubchannelPicker> pickerList = new ArrayList<>();
9290
for (ChildLbState child : children) {
9391
SubchannelPicker picker = child.getCurrentPicker();

util/src/test/java/io/grpc/util/OutlierDetectionLoadBalancerTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ public void successRateOneOutlier_configChange() {
569569
loadBalancer.acceptResolvedAddresses(buildResolvedAddress(config, servers));
570570

571571
// The PickFirstLeafLB has an extra level of indirection because of health
572-
int expectedStateChanges = PickFirstLoadBalancerProvider.isEnabledNewPickFirst() ? 16 : 12;
572+
int expectedStateChanges = PickFirstLoadBalancerProvider.isEnabledNewPickFirst() ? 8 : 12;
573573
generateLoad(ImmutableMap.of(subchannel2, Status.DEADLINE_EXCEEDED), expectedStateChanges);
574574

575575
// Move forward in time to a point where the detection timer has fired.
@@ -604,7 +604,7 @@ public void successRateOneOutlier_unejected() {
604604
assertEjectedSubchannels(ImmutableSet.of(ImmutableSet.copyOf(servers.get(0).getAddresses())));
605605

606606
// Now we produce more load, but the subchannel has started working and is no longer an outlier.
607-
int expectedStateChanges = PickFirstLoadBalancerProvider.isEnabledNewPickFirst() ? 16 : 12;
607+
int expectedStateChanges = PickFirstLoadBalancerProvider.isEnabledNewPickFirst() ? 8 : 12;
608608
generateLoad(ImmutableMap.of(), expectedStateChanges);
609609

610610
// Move forward in time to a point where the detection timer has fired.

xds/src/main/java/io/grpc/xds/WeightedRoundRobinLoadBalancer.java

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
import io.grpc.services.MetricReport;
4343
import io.grpc.util.ForwardingLoadBalancerHelper;
4444
import io.grpc.util.ForwardingSubchannel;
45-
import io.grpc.util.RoundRobinLoadBalancer;
45+
import io.grpc.util.MultiChildLoadBalancer;
4646
import io.grpc.xds.orca.OrcaOobUtil;
4747
import io.grpc.xds.orca.OrcaOobUtil.OrcaOobReportListener;
4848
import io.grpc.xds.orca.OrcaPerRequestUtil;
@@ -90,7 +90,7 @@
9090
* See related documentation: https://cloud.google.com/service-mesh/legacy/load-balancing-apis/proxyless-configure-advanced-traffic-management#custom-lb-config
9191
*/
9292
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/9885")
93-
final class WeightedRoundRobinLoadBalancer extends RoundRobinLoadBalancer {
93+
final class WeightedRoundRobinLoadBalancer extends MultiChildLoadBalancer {
9494

9595
private static final LongCounterMetricInstrument RR_FALLBACK_COUNTER;
9696
private static final LongCounterMetricInstrument ENDPOINT_WEIGHT_NOT_YET_USEABLE_COUNTER;
@@ -107,6 +107,7 @@ final class WeightedRoundRobinLoadBalancer extends RoundRobinLoadBalancer {
107107
private final long infTime;
108108
private final Ticker ticker;
109109
private String locality = "";
110+
private SubchannelPicker currentPicker = new FixedResultPicker(PickResult.withNoResult());
110111

111112
// The metric instruments are only registered once and shared by all instances of this LB.
112113
static {
@@ -209,13 +210,51 @@ public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {
209210
return acceptRetVal.status;
210211
}
211212

213+
/**
214+
* Updates picker with the list of active subchannels (state == READY).
215+
*/
212216
@Override
213-
public SubchannelPicker createReadyPicker(Collection<ChildLbState> activeList) {
217+
protected void updateOverallBalancingState() {
218+
List<ChildLbState> activeList = getReadyChildren();
219+
if (activeList.isEmpty()) {
220+
// No READY subchannels
221+
222+
// MultiChildLB will request connection immediately on subchannel IDLE.
223+
boolean isConnecting = false;
224+
for (ChildLbState childLbState : getChildLbStates()) {
225+
ConnectivityState state = childLbState.getCurrentState();
226+
if (state == ConnectivityState.CONNECTING || state == ConnectivityState.IDLE) {
227+
isConnecting = true;
228+
break;
229+
}
230+
}
231+
232+
if (isConnecting) {
233+
updateBalancingState(
234+
ConnectivityState.CONNECTING, new FixedResultPicker(PickResult.withNoResult()));
235+
} else {
236+
updateBalancingState(
237+
ConnectivityState.TRANSIENT_FAILURE, createReadyPicker(getChildLbStates()));
238+
}
239+
} else {
240+
updateBalancingState(ConnectivityState.READY, createReadyPicker(activeList));
241+
}
242+
}
243+
244+
private SubchannelPicker createReadyPicker(Collection<ChildLbState> activeList) {
214245
return new WeightedRoundRobinPicker(ImmutableList.copyOf(activeList),
215246
config.enableOobLoadReport, config.errorUtilizationPenalty, sequence, getHelper(),
216247
locality);
217248
}
218249

250+
private void updateBalancingState(ConnectivityState state, SubchannelPicker picker) {
251+
if (state != currentConnectivityState || !picker.equals(currentPicker)) {
252+
getHelper().updateBalancingState(state, picker);
253+
currentConnectivityState = state;
254+
currentPicker = picker;
255+
}
256+
}
257+
219258
@VisibleForTesting
220259
final class WeightedChildLbState extends ChildLbState {
221260

xds/src/test/java/io/grpc/xds/WeightedRoundRobinLoadBalancerTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,8 +536,8 @@ public void emptyConfig() {
536536
verify(helper, times(3)).createSubchannel(
537537
any(CreateSubchannelArgs.class));
538538
verify(helper).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
539-
assertThat(pickerCaptor.getValue().getClass().getName())
540-
.isEqualTo("io.grpc.util.RoundRobinLoadBalancer$EmptyPicker");
539+
assertThat(pickerCaptor.getValue().pickSubchannel(mockArgs))
540+
.isEqualTo(PickResult.withNoResult());
541541
int expectedCount = isEnabledHappyEyeballs() ? servers.size() + 1 : 1;
542542
assertThat(fakeClock.forwardTime(11, TimeUnit.SECONDS)).isEqualTo( expectedCount);
543543
}

0 commit comments

Comments
 (0)