xds: Stop extending RR in WRR · grpc/grpc-java@dc83446
@@ -42,7 +42,7 @@
4242import io.grpc.services.MetricReport;
4343import io.grpc.util.ForwardingLoadBalancerHelper;
4444import io.grpc.util.ForwardingSubchannel;
45-import io.grpc.util.RoundRobinLoadBalancer;
45+import io.grpc.util.MultiChildLoadBalancer;
4646import io.grpc.xds.orca.OrcaOobUtil;
4747import io.grpc.xds.orca.OrcaOobUtil.OrcaOobReportListener;
4848import io.grpc.xds.orca.OrcaPerRequestUtil;
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 {
94949595private static final LongCounterMetricInstrument RR_FALLBACK_COUNTER;
9696private static final LongCounterMetricInstrument ENDPOINT_WEIGHT_NOT_YET_USEABLE_COUNTER;
@@ -107,6 +107,7 @@ final class WeightedRoundRobinLoadBalancer extends RoundRobinLoadBalancer {
107107private final long infTime;
108108private final Ticker ticker;
109109private String locality = "";
110+private SubchannelPicker currentPicker = new FixedResultPicker(PickResult.withNoResult());
110111111112// The metric instruments are only registered once and shared by all instances of this LB.
112113static {
@@ -209,13 +210,51 @@ public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {
209210return acceptRetVal.status;
210211 }
211212213+/**
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) {
214245return new WeightedRoundRobinPicker(ImmutableList.copyOf(activeList),
215246config.enableOobLoadReport, config.errorUtilizationPenalty, sequence, getHelper(),
216247locality);
217248 }
218249250+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
220259final class WeightedChildLbState extends ChildLbState {
221260