use of io.grpc.LoadBalancer.Subchannel in project grpc-java by grpc.
the class ManagedChannelImplIdlenessTest method realTransportsHoldsOffIdleness.
@Test
public void realTransportsHoldsOffIdleness() throws Exception {
final EquivalentAddressGroup addressGroup = servers.get(1);
// Start a call, which goes to delayed transport
ClientCall<String, Integer> call = channel.newCall(method, CallOptions.DEFAULT);
call.start(mockCallListener, new Metadata());
// Verify that we have exited the idle mode
ArgumentCaptor<Helper> helperCaptor = ArgumentCaptor.forClass(null);
verify(mockLoadBalancerProvider).newLoadBalancer(helperCaptor.capture());
deliverResolutionResult();
Helper helper = helperCaptor.getValue();
assertTrue(channel.inUseStateAggregator.isInUse());
// Assume LoadBalancer has received an address, then create a subchannel.
Subchannel subchannel = createSubchannelSafely(helper, addressGroup, Attributes.EMPTY);
requestConnectionSafely(helper, subchannel);
MockClientTransportInfo t0 = newTransports.poll();
t0.listener.transportReady();
SubchannelPicker mockPicker = mock(SubchannelPicker.class);
when(mockPicker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withSubchannel(subchannel));
updateBalancingStateSafely(helper, READY, mockPicker);
// Delayed transport creates real streams in the app executor
executor.runDueTasks();
// Delayed transport exits in-use, while real transport has not entered in-use yet.
assertFalse(channel.inUseStateAggregator.isInUse());
// Now it's in-use
t0.listener.transportInUse(true);
assertTrue(channel.inUseStateAggregator.isInUse());
// As long as the transport is in-use, the channel won't go idle.
timer.forwardTime(IDLE_TIMEOUT_SECONDS * 2, TimeUnit.SECONDS);
assertTrue(channel.inUseStateAggregator.isInUse());
t0.listener.transportInUse(false);
assertFalse(channel.inUseStateAggregator.isInUse());
// And allow the channel to go idle.
timer.forwardTime(IDLE_TIMEOUT_SECONDS - 1, TimeUnit.SECONDS);
verify(mockLoadBalancer, never()).shutdown();
timer.forwardTime(1, TimeUnit.SECONDS);
verify(mockLoadBalancer).shutdown();
}
use of io.grpc.LoadBalancer.Subchannel in project grpc-java by grpc.
the class ManagedChannelImplIdlenessTest method enterIdleWhileRealTransportInProgress.
@Test
public void enterIdleWhileRealTransportInProgress() {
final EquivalentAddressGroup addressGroup = servers.get(1);
// Start a call, which goes to delayed transport
ClientCall<String, Integer> call = channel.newCall(method, CallOptions.DEFAULT);
call.start(mockCallListener, new Metadata());
// Verify that we have exited the idle mode
ArgumentCaptor<Helper> helperCaptor = ArgumentCaptor.forClass(null);
verify(mockLoadBalancerProvider).newLoadBalancer(helperCaptor.capture());
deliverResolutionResult();
Helper helper = helperCaptor.getValue();
// Create a subchannel for the real transport to happen on.
Subchannel subchannel = createSubchannelSafely(helper, addressGroup, Attributes.EMPTY);
requestConnectionSafely(helper, subchannel);
MockClientTransportInfo t0 = newTransports.poll();
t0.listener.transportReady();
SubchannelPicker mockPicker = mock(SubchannelPicker.class);
when(mockPicker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withSubchannel(subchannel));
updateBalancingStateSafely(helper, READY, mockPicker);
// Delayed transport creates real streams in the app executor
executor.runDueTasks();
// Move transport to the in-use state
t0.listener.transportInUse(true);
// Now we enter Idle mode while real transport is happening
channel.enterIdle();
// Verify that the name resolver and the load balance were shut down.
verify(mockNameResolver).shutdown();
verify(mockLoadBalancer).shutdown();
// When there are no pending streams, the call to enterIdle() should stick and
// we remain in idle mode. We verify this by making sure that the name resolver
// was not started up more than once (the initial startup).
verify(mockNameResolver, atMostOnce()).start(isA(NameResolver.Listener2.class));
}
use of io.grpc.LoadBalancer.Subchannel in project grpc-java by grpc.
the class RingHashLoadBalancerTest method subchannelLazyConnectUntilPicked.
@Test
public void subchannelLazyConnectUntilPicked() {
RingHashConfig config = new RingHashConfig(10, 100);
// one server
List<EquivalentAddressGroup> servers = createWeightedServerAddrs(1);
loadBalancer.handleResolvedAddresses(ResolvedAddresses.newBuilder().setAddresses(servers).setLoadBalancingPolicyConfig(config).build());
verify(helper).createSubchannel(any(CreateSubchannelArgs.class));
Subchannel subchannel = Iterables.getOnlyElement(subchannels.values());
verify(subchannel, never()).requestConnection();
verify(helper).updateBalancingState(eq(IDLE), pickerCaptor.capture());
// Picking subchannel triggers connection.
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()).isTrue();
assertThat(result.getSubchannel()).isNull();
verify(subchannel).requestConnection();
deliverSubchannelState(subchannel, ConnectivityStateInfo.forNonError(CONNECTING));
verify(helper).updateBalancingState(eq(CONNECTING), any(SubchannelPicker.class));
// Subchannel becomes ready, triggers pick again.
deliverSubchannelState(subchannel, ConnectivityStateInfo.forNonError(READY));
verify(helper).updateBalancingState(eq(READY), pickerCaptor.capture());
result = pickerCaptor.getValue().pickSubchannel(args);
assertThat(result.getSubchannel()).isSameInstanceAs(subchannel);
verifyNoMoreInteractions(helper);
}
use of io.grpc.LoadBalancer.Subchannel in project grpc-java by grpc.
the class RingHashLoadBalancerTest method deterministicPickWithHostsPartiallyRemoved.
@Test
public void deterministicPickWithHostsPartiallyRemoved() {
RingHashConfig config = new RingHashConfig(10, 100);
List<EquivalentAddressGroup> servers = createWeightedServerAddrs(1, 1, 1, 1, 1);
loadBalancer.handleResolvedAddresses(ResolvedAddresses.newBuilder().setAddresses(servers).setLoadBalancingPolicyConfig(config).build());
InOrder inOrder = Mockito.inOrder(helper);
inOrder.verify(helper, times(5)).createSubchannel(any(CreateSubchannelArgs.class));
inOrder.verify(helper).updateBalancingState(eq(IDLE), any(SubchannelPicker.class));
// 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));
List<EquivalentAddressGroup> updatedServers = new ArrayList<>();
for (EquivalentAddressGroup addr : servers.subList(0, 2)) {
// only server0 and server1 left
Attributes attr = addr.getAttributes().toBuilder().set(CUSTOM_KEY, "custom value").build();
updatedServers.add(new EquivalentAddressGroup(addr.getAddresses(), attr));
}
loadBalancer.handleResolvedAddresses(ResolvedAddresses.newBuilder().setAddresses(updatedServers).setLoadBalancingPolicyConfig(config).build());
verify(subchannels.get(Collections.singletonList(servers.get(0)))).updateAddresses(Collections.singletonList(updatedServers.get(0)));
verify(subchannels.get(Collections.singletonList(servers.get(1)))).updateAddresses(Collections.singletonList(updatedServers.get(1)));
inOrder.verify(helper).updateBalancingState(eq(READY), pickerCaptor.capture());
assertThat(pickerCaptor.getValue().pickSubchannel(args).getSubchannel()).isSameInstanceAs(subchannel);
verifyNoMoreInteractions(helper);
}
use of io.grpc.LoadBalancer.Subchannel 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);
}
Aggregations