Search in sources :

Example 86 with Subchannel

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();
}
Also used : Helper(io.grpc.LoadBalancer.Helper) SubchannelPicker(io.grpc.LoadBalancer.SubchannelPicker) EquivalentAddressGroup(io.grpc.EquivalentAddressGroup) Subchannel(io.grpc.LoadBalancer.Subchannel) Metadata(io.grpc.Metadata) MockClientTransportInfo(io.grpc.internal.TestUtils.MockClientTransportInfo) PickSubchannelArgs(io.grpc.LoadBalancer.PickSubchannelArgs) Test(org.junit.Test)

Example 87 with Subchannel

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));
}
Also used : Helper(io.grpc.LoadBalancer.Helper) SubchannelPicker(io.grpc.LoadBalancer.SubchannelPicker) EquivalentAddressGroup(io.grpc.EquivalentAddressGroup) Subchannel(io.grpc.LoadBalancer.Subchannel) Metadata(io.grpc.Metadata) MockClientTransportInfo(io.grpc.internal.TestUtils.MockClientTransportInfo) PickSubchannelArgs(io.grpc.LoadBalancer.PickSubchannelArgs) Test(org.junit.Test)

Example 88 with Subchannel

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);
}
Also used : SubchannelPicker(io.grpc.LoadBalancer.SubchannelPicker) PickSubchannelArgsImpl(io.grpc.internal.PickSubchannelArgsImpl) CreateSubchannelArgs(io.grpc.LoadBalancer.CreateSubchannelArgs) EquivalentAddressGroup(io.grpc.EquivalentAddressGroup) Subchannel(io.grpc.LoadBalancer.Subchannel) Metadata(io.grpc.Metadata) PickResult(io.grpc.LoadBalancer.PickResult) RingHashConfig(io.grpc.xds.RingHashLoadBalancer.RingHashConfig) PickSubchannelArgs(io.grpc.LoadBalancer.PickSubchannelArgs) Test(org.junit.Test)

Example 89 with Subchannel

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);
}
Also used : InOrder(org.mockito.InOrder) Metadata(io.grpc.Metadata) ArrayList(java.util.ArrayList) Attributes(io.grpc.Attributes) RingHashConfig(io.grpc.xds.RingHashLoadBalancer.RingHashConfig) SubchannelPicker(io.grpc.LoadBalancer.SubchannelPicker) PickSubchannelArgsImpl(io.grpc.internal.PickSubchannelArgsImpl) CreateSubchannelArgs(io.grpc.LoadBalancer.CreateSubchannelArgs) EquivalentAddressGroup(io.grpc.EquivalentAddressGroup) Subchannel(io.grpc.LoadBalancer.Subchannel) PickResult(io.grpc.LoadBalancer.PickResult) PickSubchannelArgs(io.grpc.LoadBalancer.PickSubchannelArgs) Test(org.junit.Test)

Example 90 with Subchannel

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);
}
Also used : HashMap(java.util.HashMap) Metadata(io.grpc.Metadata) RingHashConfig(io.grpc.xds.RingHashLoadBalancer.RingHashConfig) SubchannelPicker(io.grpc.LoadBalancer.SubchannelPicker) PickSubchannelArgsImpl(io.grpc.internal.PickSubchannelArgsImpl) CreateSubchannelArgs(io.grpc.LoadBalancer.CreateSubchannelArgs) EquivalentAddressGroup(io.grpc.EquivalentAddressGroup) Subchannel(io.grpc.LoadBalancer.Subchannel) PickSubchannelArgs(io.grpc.LoadBalancer.PickSubchannelArgs) Test(org.junit.Test)

Aggregations

Subchannel (io.grpc.LoadBalancer.Subchannel)125 Test (org.junit.Test)108 EquivalentAddressGroup (io.grpc.EquivalentAddressGroup)54 InOrder (org.mockito.InOrder)43 PickSubchannelArgs (io.grpc.LoadBalancer.PickSubchannelArgs)42 Metadata (io.grpc.Metadata)40 SubchannelPicker (io.grpc.LoadBalancer.SubchannelPicker)35 CreateSubchannelArgs (io.grpc.LoadBalancer.CreateSubchannelArgs)33 ForwardingSubchannel (io.grpc.util.ForwardingSubchannel)32 MockClientTransportInfo (io.grpc.internal.TestUtils.MockClientTransportInfo)30 Attributes (io.grpc.Attributes)26 ConnectivityStateInfo (io.grpc.ConnectivityStateInfo)25 ClientStreamTracer (io.grpc.ClientStreamTracer)24 Status (io.grpc.Status)23 PickResult (io.grpc.LoadBalancer.PickResult)19 CallOptions (io.grpc.CallOptions)18 ConnectivityState (io.grpc.ConnectivityState)18 Helper (io.grpc.LoadBalancer.Helper)18 SocketAddress (java.net.SocketAddress)18 ChannelLogger (io.grpc.ChannelLogger)14