use of io.grpc.LoadBalancer.PickSubchannelArgs in project grpc-java by grpc.
the class RingHashLoadBalancerTest method hostSelectionProportionalToWeights.
@Test
public void hostSelectionProportionalToWeights() {
// large ring
RingHashConfig config = new RingHashConfig(10000, 100000);
// 1:10:100
List<EquivalentAddressGroup> servers = createWeightedServerAddrs(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(2));
assertThat(ratio01).isWithin(0.03).of((double) 1 / 10);
assertThat(ratio12).isWithin(0.03).of((double) 10 / 100);
}
use of io.grpc.LoadBalancer.PickSubchannelArgs in project grpc-java by grpc.
the class RingHashLoadBalancerTest method subchannelNotAutoReconnectAfterReenteringIdle.
@Test
public void subchannelNotAutoReconnectAfterReenteringIdle() {
RingHashConfig config = new RingHashConfig(10, 100);
// one server
List<EquivalentAddressGroup> servers = createWeightedServerAddrs(1);
loadBalancer.handleResolvedAddresses(ResolvedAddresses.newBuilder().setAddresses(servers).setLoadBalancingPolicyConfig(config).build());
Subchannel subchannel = Iterables.getOnlyElement(subchannels.values());
InOrder inOrder = Mockito.inOrder(helper, subchannel);
inOrder.verify(helper).updateBalancingState(eq(IDLE), pickerCaptor.capture());
inOrder.verify(subchannel, never()).requestConnection();
// Picking subchannel triggers connection.
PickSubchannelArgs args = new PickSubchannelArgsImpl(TestMethodDescriptors.voidMethod(), new Metadata(), CallOptions.DEFAULT.withOption(XdsNameResolver.RPC_HASH_KEY, hashFunc.hashVoid()));
pickerCaptor.getValue().pickSubchannel(args);
inOrder.verify(subchannel).requestConnection();
deliverSubchannelState(subchannel, ConnectivityStateInfo.forNonError(READY));
inOrder.verify(helper).updateBalancingState(eq(READY), any(SubchannelPicker.class));
deliverSubchannelState(subchannel, ConnectivityStateInfo.forNonError(IDLE));
inOrder.verify(helper).updateBalancingState(eq(IDLE), pickerCaptor.capture());
inOrder.verify(subchannel, never()).requestConnection();
// Picking again triggers reconnection.
pickerCaptor.getValue().pickSubchannel(args);
inOrder.verify(subchannel).requestConnection();
}
use of io.grpc.LoadBalancer.PickSubchannelArgs in project grpc-java by grpc.
the class RingHashLoadBalancerTest method skipFailingHosts_firstTwoHostsFailed_pickNextFirstReady.
@Test
public void skipFailingHosts_firstTwoHostsFailed_pickNextFirstReady() {
// 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 and server2 to force trying server1.
deliverSubchannelState(subchannels.get(Collections.singletonList(servers.get(0))), ConnectivityStateInfo.forTransientFailure(Status.UNAVAILABLE.withDescription("unreachable")));
deliverSubchannelState(subchannels.get(Collections.singletonList(servers.get(2))), ConnectivityStateInfo.forTransientFailure(Status.PERMISSION_DENIED.withDescription("permission denied")));
verify(helper).updateBalancingState(eq(TRANSIENT_FAILURE), pickerCaptor.capture());
verify(subchannels.get(Collections.singletonList(servers.get(1)))).requestConnection();
PickResult result = pickerCaptor.getValue().pickSubchannel(args);
// fail the RPC
assertThat(result.getStatus().isOk()).isFalse();
assertThat(result.getStatus().getCode()).isEqualTo(// with error status for the original server hit by hash
Code.UNAVAILABLE);
assertThat(result.getStatus().getDescription()).isEqualTo("unreachable");
verify(subchannels.get(Collections.singletonList(servers.get(1))), times(2)).requestConnection();
// Now connecting to server1.
deliverSubchannelState(subchannels.get(Collections.singletonList(servers.get(1))), ConnectivityStateInfo.forNonError(CONNECTING));
verify(helper, times(2)).updateBalancingState(eq(TRANSIENT_FAILURE), pickerCaptor.capture());
result = pickerCaptor.getValue().pickSubchannel(args);
// fail the RPC
assertThat(result.getStatus().isOk()).isFalse();
assertThat(result.getStatus().getCode()).isEqualTo(// with error status for the original server hit by hash
Code.UNAVAILABLE);
assertThat(result.getStatus().getDescription()).isEqualTo("unreachable");
// Simulate server1 becomes READY.
deliverSubchannelState(subchannels.get(Collections.singletonList(servers.get(1))), ConnectivityStateInfo.forNonError(READY));
verify(helper).updateBalancingState(eq(READY), pickerCaptor.capture());
result = pickerCaptor.getValue().pickSubchannel(args);
// succeed
assertThat(result.getStatus().isOk()).isTrue();
// with server1
assertThat(result.getSubchannel().getAddresses()).isEqualTo(servers.get(1));
}
use of io.grpc.LoadBalancer.PickSubchannelArgs in project grpc-java by grpc.
the class PriorityLoadBalancerTest method readyToConnectDoesNotFailOverButUpdatesPicker.
@Test
public void readyToConnectDoesNotFailOverButUpdatesPicker() {
PriorityChildConfig priorityChildConfig0 = new PriorityChildConfig(new PolicySelection(fooLbProvider, new Object()), true);
PriorityChildConfig priorityChildConfig1 = new PriorityChildConfig(new PolicySelection(fooLbProvider, new Object()), true);
PriorityLbConfig priorityLbConfig = new PriorityLbConfig(ImmutableMap.of("p0", priorityChildConfig0, "p1", priorityChildConfig1), ImmutableList.of("p0", "p1"));
priorityLb.handleResolvedAddresses(ResolvedAddresses.newBuilder().setAddresses(ImmutableList.<EquivalentAddressGroup>of()).setLoadBalancingPolicyConfig(priorityLbConfig).build());
assertThat(fooBalancers).hasSize(1);
assertThat(fooHelpers).hasSize(1);
Helper helper0 = Iterables.getOnlyElement(fooHelpers);
// p0 gets READY.
final Subchannel subchannel0 = mock(Subchannel.class);
helper0.updateBalancingState(READY, new SubchannelPicker() {
@Override
public PickResult pickSubchannel(PickSubchannelArgs args) {
return PickResult.withSubchannel(subchannel0);
}
});
assertCurrentPickerPicksSubchannel(subchannel0);
// p0 goes to CONNECTING
helper0.updateBalancingState(IDLE, BUFFER_PICKER);
assertCurrentPickerIsBufferPicker();
// no failover happened
assertThat(fooBalancers).hasSize(1);
assertThat(fooHelpers).hasSize(1);
// resolution update without priority change does not trigger failover
Attributes.Key<String> fooKey = Attributes.Key.create("fooKey");
priorityLb.handleResolvedAddresses(ResolvedAddresses.newBuilder().setAddresses(ImmutableList.<EquivalentAddressGroup>of()).setLoadBalancingPolicyConfig(priorityLbConfig).setAttributes(Attributes.newBuilder().set(fooKey, "barVal").build()).build());
assertCurrentPickerIsBufferPicker();
// no failover happened
assertThat(fooBalancers).hasSize(1);
assertThat(fooHelpers).hasSize(1);
}
use of io.grpc.LoadBalancer.PickSubchannelArgs in project grpc-java by grpc.
the class ConfigSelectingClientCallTest method configSelectorInterceptsCall.
@Test
public void configSelectorInterceptsCall() {
Map<String, ?> rawMethodConfig = ImmutableMap.of("retryPolicy", ImmutableMap.of("maxAttempts", 3.0D, "initialBackoff", "1s", "maxBackoff", "10s", "backoffMultiplier", 1.5D, "retryableStatusCodes", ImmutableList.of("UNAVAILABLE")));
final MethodInfo methodInfo = new MethodInfo(rawMethodConfig, true, 4, 4);
final Metadata.Key<String> metadataKey = Metadata.Key.of("test", Metadata.ASCII_STRING_MARSHALLER);
final CallOptions.Key<String> callOptionsKey = CallOptions.Key.create("test");
InternalConfigSelector configSelector = new InternalConfigSelector() {
@Override
public Result selectConfig(final PickSubchannelArgs args) {
ManagedChannelServiceConfig config = new ManagedChannelServiceConfig(methodInfo, ImmutableMap.<String, MethodInfo>of(), ImmutableMap.<String, MethodInfo>of(), null, null, null);
return Result.newBuilder().setConfig(config).setInterceptor(// An interceptor that mutates CallOptions based on headers value.
new ClientInterceptor() {
String value = args.getHeaders().get(metadataKey);
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
callOptions = callOptions.withOption(callOptionsKey, value);
return next.newCall(method, callOptions);
}
}).build();
}
};
ClientCall<Void, Void> configSelectingClientCall = new ConfigSelectingClientCall<>(configSelector, channel, MoreExecutors.directExecutor(), method, CallOptions.DEFAULT.withAuthority("bar.authority"));
Metadata metadata = new Metadata();
metadata.put(metadataKey, "fooValue");
configSelectingClientCall.start(callListener, metadata);
assertThat(call.callOptions.getAuthority()).isEqualTo("bar.authority");
assertThat(call.callOptions.getOption(MethodInfo.KEY)).isEqualTo(methodInfo);
assertThat(call.callOptions.getOption(callOptionsKey)).isEqualTo("fooValue");
}
Aggregations