xds: throw away subchannel references after ring_hash is shutdown (#8140)

Similar to 368c43aec4. 

Clean up subchannels after the RingHashLoadBalancer itself is shutdown to prevent further balancing state updates being propagated to the upstream.

Note this should not be considered as a fix for any problem anybody is noticing. Upstreams of RingHashLoadBalancer should not rely on this, it should still have its own logic for maintaining the lifecycle of downstream LB and ignore invalid upcalls when necessary.
This commit is contained in:
Chengyuan Zhang 2021-05-04 13:35:37 -07:00 committed by GitHub
parent 16eb5a47ec
commit ee000f0dc1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 0 deletions

View File

@ -188,6 +188,7 @@ final class RingHashLoadBalancer extends LoadBalancer {
for (Subchannel subchannel : subchannels.values()) {
shutdownSubchannel(subchannel);
}
subchannels.clear();
}
private void updateBalancingState() {

View File

@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import static io.grpc.ConnectivityState.CONNECTING;
import static io.grpc.ConnectivityState.IDLE;
import static io.grpc.ConnectivityState.READY;
import static io.grpc.ConnectivityState.SHUTDOWN;
import static io.grpc.ConnectivityState.TRANSIENT_FAILURE;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
@ -336,6 +337,26 @@ public class RingHashLoadBalancerTest {
verify(helper).updateBalancingState(eq(READY), any(SubchannelPicker.class));
}
@Test
public void ignoreShutdownSubchannelStateChange() {
RingHashConfig config = new RingHashConfig(10, 100);
List<EquivalentAddressGroup> servers = createWeightedServerAddrs(1, 1, 1);
loadBalancer.handleResolvedAddresses(
ResolvedAddresses.newBuilder()
.setAddresses(servers).setLoadBalancingPolicyConfig(config).build());
verify(helper, times(3)).createSubchannel(any(CreateSubchannelArgs.class));
verify(helper).updateBalancingState(eq(IDLE), any(SubchannelPicker.class));
loadBalancer.shutdown();
for (Subchannel sc : subchannels.values()) {
verify(sc).shutdown();
// When the subchannel is being shut down, a SHUTDOWN connectivity state is delivered
// back to the subchannel state listener.
deliverSubchannelState(sc, ConnectivityStateInfo.forNonError(SHUTDOWN));
}
verifyNoMoreInteractions(helper);
}
@Test
public void deterministicPickWithHostsPartiallyRemoved() {
RingHashConfig config = new RingHashConfig(10, 100);