use of io.grpc.internal.PickSubchannelArgsImpl in project grpc-java by grpc.
the class RingHashLoadBalancerTest method skipFailingHosts_pickNextNonFailingHostInFirstTwoHosts.
@Test
public void skipFailingHosts_pickNextNonFailingHostInFirstTwoHosts() {
// Map each server address to exactly one ring entry.
RingHashConfig config = new RingHashConfig(3, 3);
List<EquivalentAddressGroup> servers = createWeightedServerAddrs(1, 1, 1);
loadBalancer.handleResolvedAddresses(ResolvedAddresses.newBuilder().setAddresses(servers).setLoadBalancingPolicyConfig(config).build());
verify(helper, times(3)).createSubchannel(any(CreateSubchannelArgs.class));
// initial IDLE
verify(helper).updateBalancingState(eq(IDLE), any(SubchannelPicker.class));
reset(helper);
// ring:
// "[FakeSocketAddress-server1]_0"
// "[FakeSocketAddress-server0]_0"
// "[FakeSocketAddress-server2]_0"
long rpcHash = hashFunc.hashAsciiString("[FakeSocketAddress-server0]_0");
PickSubchannelArgs args = new PickSubchannelArgsImpl(TestMethodDescriptors.voidMethod(), new Metadata(), CallOptions.DEFAULT.withOption(XdsNameResolver.RPC_HASH_KEY, rpcHash));
// Bring down server0 to force trying server2.
deliverSubchannelState(subchannels.get(Collections.singletonList(servers.get(0))), ConnectivityStateInfo.forTransientFailure(Status.UNAVAILABLE.withDescription("unreachable")));
verify(helper).updateBalancingState(eq(IDLE), pickerCaptor.capture());
PickResult result = pickerCaptor.getValue().pickSubchannel(args);
assertThat(result.getStatus().isOk()).isTrue();
// buffer request
assertThat(result.getSubchannel()).isNull();
verify(subchannels.get(Collections.singletonList(servers.get(2)))).requestConnection();
verify(subchannels.get(Collections.singletonList(servers.get(1))), never()).requestConnection();
deliverSubchannelState(subchannels.get(Collections.singletonList(servers.get(2))), ConnectivityStateInfo.forNonError(CONNECTING));
verify(helper).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
result = pickerCaptor.getValue().pickSubchannel(args);
assertThat(result.getStatus().isOk()).isTrue();
// buffer request
assertThat(result.getSubchannel()).isNull();
deliverSubchannelState(subchannels.get(Collections.singletonList(servers.get(2))), ConnectivityStateInfo.forNonError(READY));
verify(helper).updateBalancingState(eq(READY), pickerCaptor.capture());
result = pickerCaptor.getValue().pickSubchannel(args);
assertThat(result.getStatus().isOk()).isTrue();
assertThat(result.getSubchannel().getAddresses()).isEqualTo(servers.get(2));
}
use of io.grpc.internal.PickSubchannelArgsImpl in project grpc-java by grpc.
the class RingHashLoadBalancerTest method deterministicPickWithNewHostsAdded.
@Test
public void deterministicPickWithNewHostsAdded() {
RingHashConfig config = new RingHashConfig(10, 100);
// server0 and server1
List<EquivalentAddressGroup> servers = createWeightedServerAddrs(1, 1);
loadBalancer.handleResolvedAddresses(ResolvedAddresses.newBuilder().setAddresses(servers).setLoadBalancingPolicyConfig(config).build());
InOrder inOrder = Mockito.inOrder(helper);
inOrder.verify(helper, times(2)).createSubchannel(any(CreateSubchannelArgs.class));
inOrder.verify(helper).updateBalancingState(eq(IDLE), pickerCaptor.capture());
// Bring all subchannels to READY so that next pick always succeeds.
for (Subchannel subchannel : subchannels.values()) {
deliverSubchannelState(subchannel, ConnectivityStateInfo.forNonError(READY));
inOrder.verify(helper).updateBalancingState(eq(READY), pickerCaptor.capture());
}
// Simulate rpc hash hits one ring entry exactly for server1.
long rpcHash = hashFunc.hashAsciiString("[FakeSocketAddress-server1]_0");
PickSubchannelArgs args = new PickSubchannelArgsImpl(TestMethodDescriptors.voidMethod(), new Metadata(), CallOptions.DEFAULT.withOption(XdsNameResolver.RPC_HASH_KEY, rpcHash));
pickerCaptor.getValue().pickSubchannel(args);
PickResult result = pickerCaptor.getValue().pickSubchannel(args);
Subchannel subchannel = result.getSubchannel();
assertThat(subchannel.getAddresses()).isEqualTo(servers.get(1));
// server2, server3, server4 added
servers = createWeightedServerAddrs(1, 1, 1, 1, 1);
loadBalancer.handleResolvedAddresses(ResolvedAddresses.newBuilder().setAddresses(servers).setLoadBalancingPolicyConfig(config).build());
inOrder.verify(helper, times(3)).createSubchannel(any(CreateSubchannelArgs.class));
inOrder.verify(helper).updateBalancingState(eq(READY), pickerCaptor.capture());
assertThat(pickerCaptor.getValue().pickSubchannel(args).getSubchannel()).isSameInstanceAs(subchannel);
verifyNoMoreInteractions(helper);
}
use of io.grpc.internal.PickSubchannelArgsImpl in project grpc-java by grpc.
the class RingHashLoadBalancerTest method allSubchannelsInTransientFailure.
@Test
public void allSubchannelsInTransientFailure() {
// Map each server address to exactly one ring entry.
RingHashConfig config = new RingHashConfig(3, 3);
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));
// Bring all subchannels to TRANSIENT_FAILURE.
for (Subchannel subchannel : subchannels.values()) {
deliverSubchannelState(subchannel, ConnectivityStateInfo.forTransientFailure(Status.UNAVAILABLE.withDescription(subchannel.getAddresses().getAddresses() + " unreachable")));
}
verify(helper, atLeastOnce()).updateBalancingState(eq(TRANSIENT_FAILURE), pickerCaptor.capture());
// Picking subchannel triggers connection. RPC hash hits server0.
PickSubchannelArgs args = new PickSubchannelArgsImpl(TestMethodDescriptors.voidMethod(), new Metadata(), CallOptions.DEFAULT.withOption(XdsNameResolver.RPC_HASH_KEY, hashFunc.hashVoid()));
PickResult result = pickerCaptor.getValue().pickSubchannel(args);
assertThat(result.getStatus().isOk()).isFalse();
assertThat(result.getStatus().getCode()).isEqualTo(Code.UNAVAILABLE);
assertThat(result.getStatus().getDescription()).isEqualTo("[FakeSocketAddress-server0] unreachable");
}
use of io.grpc.internal.PickSubchannelArgsImpl in project grpc-java by grpc.
the class RingHashLoadBalancerTest method hostSelectionProportionalToRepeatedAddressCount.
@Test
public void hostSelectionProportionalToRepeatedAddressCount() {
RingHashConfig config = new RingHashConfig(10000, 100000);
// 1:10:100
List<EquivalentAddressGroup> servers = createRepeatedServerAddrs(1, 10, 100);
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));
// Bring all subchannels to READY.
Map<EquivalentAddressGroup, Integer> pickCounts = new HashMap<>();
for (Subchannel subchannel : subchannels.values()) {
deliverSubchannelState(subchannel, ConnectivityStateInfo.forNonError(READY));
pickCounts.put(subchannel.getAddresses(), 0);
}
verify(helper, times(3)).updateBalancingState(eq(READY), pickerCaptor.capture());
SubchannelPicker picker = pickerCaptor.getValue();
for (int i = 0; i < 10000; i++) {
long hash = hashFunc.hashInt(i);
PickSubchannelArgs args = new PickSubchannelArgsImpl(TestMethodDescriptors.voidMethod(), new Metadata(), CallOptions.DEFAULT.withOption(XdsNameResolver.RPC_HASH_KEY, hash));
Subchannel pickedSubchannel = picker.pickSubchannel(args).getSubchannel();
EquivalentAddressGroup addr = pickedSubchannel.getAddresses();
pickCounts.put(addr, pickCounts.get(addr) + 1);
}
// Actual distribution: server0 = 104, server1 = 808, server2 = 9088
double ratio01 = (double) pickCounts.get(servers.get(0)) / pickCounts.get(servers.get(1));
double ratio12 = (double) pickCounts.get(servers.get(1)) / pickCounts.get(servers.get(11));
assertThat(ratio01).isWithin(0.03).of((double) 1 / 10);
assertThat(ratio12).isWithin(0.03).of((double) 10 / 100);
}
use of io.grpc.internal.PickSubchannelArgsImpl in project grpc-java by grpc.
the class RlsLoadBalancerTest method lb_working_withoutDefaultTarget.
@Test
public void lb_working_withoutDefaultTarget() throws Exception {
defaultTarget = "";
deliverResolvedAddresses();
InOrder inOrder = inOrder(helper);
inOrder.verify(helper).updateBalancingState(eq(ConnectivityState.CONNECTING), pickerCaptor.capture());
SubchannelPicker picker = pickerCaptor.getValue();
Metadata headers = new Metadata();
PickResult res = picker.pickSubchannel(new PickSubchannelArgsImpl(fakeSearchMethod, headers, CallOptions.DEFAULT));
inOrder.verify(helper).createSubchannel(any(CreateSubchannelArgs.class));
inOrder.verify(helper).updateBalancingState(eq(ConnectivityState.CONNECTING), any(SubchannelPicker.class));
inOrder.verifyNoMoreInteractions();
assertThat(res.getStatus().isOk()).isTrue();
assertThat(subchannels).hasSize(1);
FakeSubchannel searchSubchannel = subchannels.getLast();
searchSubchannel.updateState(ConnectivityStateInfo.forNonError(ConnectivityState.READY));
inOrder.verify(helper).updateBalancingState(eq(ConnectivityState.READY), pickerCaptor.capture());
inOrder.verifyNoMoreInteractions();
assertThat(subchannelIsReady(res.getSubchannel())).isTrue();
assertThat(res.getSubchannel().getAddresses()).isEqualTo(searchSubchannel.getAddresses());
assertThat(res.getSubchannel().getAttributes()).isEqualTo(searchSubchannel.getAttributes());
// rescue should be pending status although the overall channel state is READY
picker = pickerCaptor.getValue();
res = picker.pickSubchannel(new PickSubchannelArgsImpl(fakeRescueMethod, headers, CallOptions.DEFAULT));
inOrder.verify(helper).createSubchannel(any(CreateSubchannelArgs.class));
// other rls picker itself is ready due to first channel.
inOrder.verify(helper).updateBalancingState(eq(ConnectivityState.READY), pickerCaptor.capture());
inOrder.verifyNoMoreInteractions();
assertThat(res.getStatus().isOk()).isTrue();
assertThat(subchannelIsReady(res.getSubchannel())).isFalse();
assertThat(subchannels).hasSize(2);
FakeSubchannel rescueSubchannel = subchannels.getLast();
// search subchannel is down, rescue subchannel is still connecting
searchSubchannel.updateState(ConnectivityStateInfo.forTransientFailure(Status.NOT_FOUND));
inOrder.verify(helper).updateBalancingState(eq(ConnectivityState.CONNECTING), pickerCaptor.capture());
rescueSubchannel.updateState(ConnectivityStateInfo.forNonError(ConnectivityState.READY));
inOrder.verify(helper).updateBalancingState(eq(ConnectivityState.READY), pickerCaptor.capture());
// search method will fail because there is no fallback target.
picker = pickerCaptor.getValue();
res = picker.pickSubchannel(new PickSubchannelArgsImpl(fakeSearchMethod, headers, CallOptions.DEFAULT));
assertThat(res.getStatus().isOk()).isFalse();
assertThat(subchannelIsReady(res.getSubchannel())).isFalse();
res = picker.pickSubchannel(new PickSubchannelArgsImpl(fakeRescueMethod, headers, CallOptions.DEFAULT));
assertThat(subchannelIsReady(res.getSubchannel())).isTrue();
assertThat(res.getSubchannel().getAddresses()).isEqualTo(rescueSubchannel.getAddresses());
assertThat(res.getSubchannel().getAttributes()).isEqualTo(rescueSubchannel.getAttributes());
// all channels are failed
rescueSubchannel.updateState(ConnectivityStateInfo.forTransientFailure(Status.NOT_FOUND));
inOrder.verify(helper).updateBalancingState(eq(ConnectivityState.TRANSIENT_FAILURE), pickerCaptor.capture());
inOrder.verifyNoMoreInteractions();
}
Aggregations