core: Enable outlier detection unit test (#9493)

Implements a fake load balancer with round robin like behavior in order
to test an outlier detection scenario where a subchannel goes from
having multiple associated addresses to one.
This commit is contained in:
Terry Wilson 2022-08-29 15:23:41 -07:00 committed by GitHub
parent 6131a85196
commit db05295fde
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 56 additions and 7 deletions

View File

@ -58,6 +58,7 @@ import io.grpc.util.OutlierDetectionLoadBalancer.OutlierDetectionLoadBalancerCon
import io.grpc.util.OutlierDetectionLoadBalancer.OutlierDetectionSubchannel;
import io.grpc.util.OutlierDetectionLoadBalancer.SuccessRateOutlierEjectionAlgorithm;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
@ -67,7 +68,6 @@ import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -112,6 +112,13 @@ public class OutlierDetectionLoadBalancerTest {
return mockChildLb;
}
};
private final LoadBalancerProvider fakeLbProvider = new StandardLoadBalancerProvider(
"fake_policy") {
@Override
public LoadBalancer newLoadBalancer(Helper helper) {
return new FakeLoadBalancer(helper);
}
};
private final LoadBalancerProvider roundRobinLbProvider = new StandardLoadBalancerProvider(
"round_robin") {
@Override
@ -877,11 +884,8 @@ public class OutlierDetectionLoadBalancerTest {
/**
* A subchannel with multiple addresses will again become eligible for outlier detection if it
* receives an update with a single address.
*
* <p>TODO: Figure out how to test this scenario, round_robin does not support multiple addresses
* and fails the transition from multiple addresses to single.
*/
@Ignore
@Test
public void subchannelUpdateAddress_multipleReplacedWithSingle() {
OutlierDetectionLoadBalancerConfig config = new OutlierDetectionLoadBalancerConfig.Builder()
.setMaxEjectionPercent(50)
@ -889,11 +893,11 @@ public class OutlierDetectionLoadBalancerTest {
new FailurePercentageEjection.Builder()
.setMinimumHosts(3)
.setRequestVolume(10).build())
.setChildPolicy(new PolicySelection(roundRobinLbProvider, null)).build();
.setChildPolicy(new PolicySelection(fakeLbProvider, null)).build();
loadBalancer.handleResolvedAddresses(buildResolvedAddress(config, servers));
generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED), 7);
generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED), 6);
// Move forward in time to a point where the detection timer has fired.
forwardTime(config);
@ -1110,4 +1114,49 @@ public class OutlierDetectionLoadBalancerTest {
.isEqualTo(addresses.contains(entry.getKey()));
}
}
/** Round robin like fake load balancer. */
private static final class FakeLoadBalancer extends LoadBalancer {
private final Helper helper;
List<Subchannel> subchannelList;
int lastPickIndex = -1;
FakeLoadBalancer(Helper helper) {
this.helper = helper;
}
@Override
public void handleResolvedAddresses(ResolvedAddresses resolvedAddresses) {
subchannelList = new ArrayList<>();
for (EquivalentAddressGroup eag: resolvedAddresses.getAddresses()) {
Subchannel subchannel = helper.createSubchannel(CreateSubchannelArgs.newBuilder()
.setAddresses(eag).build());
subchannelList.add(subchannel);
subchannel.start(mock(SubchannelStateListener.class));
deliverSubchannelState(READY);
}
}
@Override
public void handleNameResolutionError(Status error) {
}
@Override
public void shutdown() {
}
void deliverSubchannelState(ConnectivityState state) {
SubchannelPicker picker = new SubchannelPicker() {
@Override
public PickResult pickSubchannel(PickSubchannelArgs args) {
if (lastPickIndex < 0 || lastPickIndex > subchannelList.size() - 1) {
lastPickIndex = 0;
}
return PickResult.withSubchannel(subchannelList.get(lastPickIndex++));
}
};
helper.updateBalancingState(state, picker);
}
}
}