Skip to content

Commit

Permalink
Remove implicit requestConnection() on IDLE from MultiChildLB
Browse files Browse the repository at this point in the history
One LB no longer needs to extend ChildLbState and one has to start, so
it is a bit of a wash. There are more LBs that need the auto-request
logic, but if we have an API where subclasses override it without
calling super then we can't change the implementation in the future.
Adding behavior on top of a base class allows subclasses to call super,
which lets the base class change over time.
  • Loading branch information
ejona86 committed Aug 12, 2024
1 parent 4ab3422 commit a6f8ebf
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 52 deletions.
5 changes: 0 additions & 5 deletions util/src/main/java/io/grpc/util/MultiChildLoadBalancer.java
Original file line number Diff line number Diff line change
Expand Up @@ -456,8 +456,6 @@ protected class ChildLbStateHelper extends ForwardingLoadBalancerHelper {
/**
* Update current state and picker for this child and then use
* {@link #updateOverallBalancingState()} for the parent LB.
*
* <p/>Override this if you don't want to automatically request a connection when in IDLE
*/
@Override
public void updateBalancingState(final ConnectivityState newState,
Expand All @@ -471,9 +469,6 @@ public void updateBalancingState(final ConnectivityState newState,
// If we are already in the process of resolving addresses, the overall balancing state
// will be updated at the end of it, and we don't need to trigger that update here.
if (!resolvingAddresses) {
if (newState == IDLE) {
lb.requestConnection();
}
updateOverallBalancingState();
}
}
Expand Down
19 changes: 19 additions & 0 deletions util/src/main/java/io/grpc/util/RoundRobinLoadBalancer.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,25 @@ private SubchannelPicker createReadyPicker(Collection<ChildLbState> children) {
return new ReadyPicker(pickerList, sequence);
}

@Override
protected ChildLbState createChildLbState(Object key, Object policyConfig,
SubchannelPicker initialPicker, ResolvedAddresses resolvedAddresses) {
return new ChildLbState(key, pickFirstLbProvider, policyConfig, initialPicker) {
@Override
protected ChildLbStateHelper createChildHelper() {
return new ChildLbStateHelper() {
@Override
public void updateBalancingState(ConnectivityState newState, SubchannelPicker newPicker) {
super.updateBalancingState(newState, newPicker);
if (!resolvingAddresses && newState == IDLE) {
getLb().requestConnection();
}
}
};
}
};
}

@VisibleForTesting
static class ReadyPicker extends SubchannelPicker {
private final List<SubchannelPicker> subchannelPickers; // non-empty
Expand Down
13 changes: 13 additions & 0 deletions xds/src/main/java/io/grpc/xds/LeastRequestLoadBalancer.java
Original file line number Diff line number Diff line change
Expand Up @@ -328,5 +328,18 @@ public LeastRequestLbState(Object key, LoadBalancerProvider policyProvider,
int getActiveRequests() {
return activeRequests.get();
}

@Override
protected ChildLbStateHelper createChildHelper() {
return new ChildLbStateHelper() {
@Override
public void updateBalancingState(ConnectivityState newState, SubchannelPicker newPicker) {
super.updateBalancingState(newState, newPicker);
if (!resolvingAddresses && newState == IDLE) {
getLb().requestConnection();
}
}
};
}
}
}
49 changes: 6 additions & 43 deletions xds/src/main/java/io/grpc/xds/RingHashLoadBalancer.java
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ protected void updateOverallBalancingState() {
@Override
protected ChildLbState createChildLbState(Object key, Object policyConfig,
SubchannelPicker initialPicker, ResolvedAddresses resolvedAddresses) {
return new RingHashChildLbState((Endpoint)key);
return new ChildLbState(key, lazyLbFactory, null, EMPTY_PICKER);
}

private Status validateAddrList(List<EquivalentAddressGroup> addrList) {
Expand Down Expand Up @@ -358,7 +358,7 @@ private RingHashPicker(
this.ring = ring;
pickableSubchannels = new HashMap<>(subchannels.size());
for (Map.Entry<Object, ChildLbState> entry : subchannels.entrySet()) {
RingHashChildLbState childLbState = (RingHashChildLbState) entry.getValue();
ChildLbState childLbState = entry.getValue();
pickableSubchannels.put((Endpoint)entry.getKey(),
new SubchannelView(childLbState, childLbState.getCurrentState()));
}
Expand Down Expand Up @@ -405,7 +405,7 @@ public PickResult pickSubchannel(PickSubchannelArgs args) {
for (int i = 0; i < ring.size(); i++) {
int index = (targetIndex + i) % ring.size();
SubchannelView subchannelView = pickableSubchannels.get(ring.get(index).addrKey);
RingHashChildLbState childLbState = subchannelView.childLbState;
ChildLbState childLbState = subchannelView.childLbState;

if (subchannelView.connectivityState == READY) {
return childLbState.getCurrentPicker().pickSubchannel(args);
Expand All @@ -427,7 +427,7 @@ public PickResult pickSubchannel(PickSubchannelArgs args) {
}

// return the pick from the original subchannel hit by hash, which is probably an error
RingHashChildLbState originalSubchannel =
ChildLbState originalSubchannel =
pickableSubchannels.get(ring.get(targetIndex).addrKey).childLbState;
return originalSubchannel.getCurrentPicker().pickSubchannel(args);
}
Expand All @@ -439,10 +439,10 @@ public PickResult pickSubchannel(PickSubchannelArgs args) {
* state changes.
*/
private static final class SubchannelView {
private final RingHashChildLbState childLbState;
private final ChildLbState childLbState;
private final ConnectivityState connectivityState;

private SubchannelView(RingHashChildLbState childLbState, ConnectivityState state) {
private SubchannelView(ChildLbState childLbState, ConnectivityState state) {
this.childLbState = childLbState;
this.connectivityState = state;
}
Expand Down Expand Up @@ -487,41 +487,4 @@ public String toString() {
.toString();
}
}

class RingHashChildLbState extends MultiChildLoadBalancer.ChildLbState {

public RingHashChildLbState(Endpoint key) {
super(key, lazyLbFactory, null, EMPTY_PICKER);
}

@Override
protected ChildLbStateHelper createChildHelper() {
return new RingHashChildHelper();
}

// Need to expose this to the LB class
@Override
protected void shutdown() {
super.shutdown();
}

private class RingHashChildHelper extends ChildLbStateHelper {
@Override
public void updateBalancingState(final ConnectivityState newState,
final SubchannelPicker newPicker) {
setCurrentState(newState);
setCurrentPicker(newPicker);

if (getChildLbState(getKey()) == null) {
return;
}

// If we are already in the process of resolving addresses, the overall balancing state
// will be updated at the end of it, and we don't need to trigger that update here.
if (!resolvingAddresses) {
updateOverallBalancingState();
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,14 @@ final class WrrChildLbStateHelper extends ChildLbStateHelper {
public Subchannel createSubchannel(CreateSubchannelArgs args) {
return new WrrSubchannel(super.createSubchannel(args), WeightedChildLbState.this);
}

@Override
public void updateBalancingState(ConnectivityState newState, SubchannelPicker newPicker) {
super.updateBalancingState(newState, newPicker);
if (!resolvingAddresses && newState == ConnectivityState.IDLE) {
getLb().requestConnection();
}
}
}

final class OrcaReportListener implements OrcaPerRequestReportListener, OrcaOobReportListener {
Expand Down
6 changes: 2 additions & 4 deletions xds/src/test/java/io/grpc/xds/RingHashLoadBalancerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@
import io.grpc.testing.TestMethodDescriptors;
import io.grpc.util.AbstractTestHelper;
import io.grpc.util.MultiChildLoadBalancer.ChildLbState;
import io.grpc.xds.RingHashLoadBalancer.RingHashChildLbState;
import io.grpc.xds.RingHashLoadBalancer.RingHashConfig;
import java.lang.Thread.UncaughtExceptionHandler;
import java.net.SocketAddress;
Expand Down Expand Up @@ -177,8 +176,7 @@ public void subchannelNotAutoReconnectAfterReenteringIdle() {
assertThat(addressesAcceptanceStatus.isOk()).isTrue();
verify(helper).updateBalancingState(eq(IDLE), pickerCaptor.capture());

RingHashChildLbState childLbState =
(RingHashChildLbState) loadBalancer.getChildLbStates().iterator().next();
ChildLbState childLbState = loadBalancer.getChildLbStates().iterator().next();
assertThat(subchannels.get(Collections.singletonList(childLbState.getEag()))).isNull();

// Picking subchannel triggers connection.
Expand Down Expand Up @@ -422,7 +420,7 @@ public void skipFailingHosts_pickNextNonFailingHost() {
assertThat(addressesAcceptanceStatus.isOk()).isTrue();

// Create subchannel for the first address
((RingHashChildLbState) loadBalancer.getChildLbStateEag(servers.get(0))).getCurrentPicker()
loadBalancer.getChildLbStateEag(servers.get(0)).getCurrentPicker()
.pickSubchannel(getDefaultPickSubchannelArgs(hashFunc.hashVoid()));
verifyConnection(1);

Expand Down

0 comments on commit a6f8ebf

Please sign in to comment.