Search in sources :

Example 6 with SubchannelPicker

use of io.grpc.LoadBalancer.SubchannelPicker in project grpc-java by grpc.

the class ManagedChannelImplIdlenessTest method oobTransportDoesNotAffectIdleness.

@Test
public void oobTransportDoesNotAffectIdleness() {
    // 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(mockLoadBalancerFactory).newLoadBalancer(helperCaptor.capture());
    Helper helper = helperCaptor.getValue();
    // Fail the RPC
    SubchannelPicker failingPicker = mock(SubchannelPicker.class);
    when(failingPicker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withError(Status.UNAVAILABLE));
    helper.updatePicker(failingPicker);
    executor.runDueTasks();
    verify(mockCallListener).onClose(same(Status.UNAVAILABLE), any(Metadata.class));
    // ... so that the channel resets its in-use state
    assertFalse(channel.inUseStateAggregator.isInUse());
    // Now make an RPC on an OOB channel
    ManagedChannel oob = helper.createOobChannel(addressGroupList.get(0), "oobauthority");
    verify(mockTransportFactory, never()).newClientTransport(any(SocketAddress.class), same("oobauthority"), same(USER_AGENT));
    ClientCall<String, Integer> oobCall = oob.newCall(method, CallOptions.DEFAULT);
    oobCall.start(mockCallListener2, new Metadata());
    verify(mockTransportFactory).newClientTransport(any(SocketAddress.class), same("oobauthority"), same(USER_AGENT));
    MockClientTransportInfo oobTransportInfo = newTransports.poll();
    assertEquals(0, newTransports.size());
    // The OOB transport reports in-use state
    oobTransportInfo.listener.transportInUse(true);
    // But it won't stop the channel from going idle
    verify(mockLoadBalancer, never()).shutdown();
    timer.forwardTime(IDLE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
    verify(mockLoadBalancer).shutdown();
}
Also used : Helper(io.grpc.LoadBalancer.Helper) SubchannelPicker(io.grpc.LoadBalancer.SubchannelPicker) Metadata(io.grpc.Metadata) ManagedChannel(io.grpc.ManagedChannel) PickSubchannelArgs(io.grpc.LoadBalancer.PickSubchannelArgs) MockClientTransportInfo(io.grpc.internal.TestUtils.MockClientTransportInfo) Matchers.anyString(org.mockito.Matchers.anyString) SocketAddress(java.net.SocketAddress) Test(org.junit.Test)

Example 7 with SubchannelPicker

use of io.grpc.LoadBalancer.SubchannelPicker in project grpc-java by grpc.

the class ManagedChannelImplIdlenessTest method realTransportsHoldsOffIdleness.

@Test
public void realTransportsHoldsOffIdleness() throws Exception {
    final EquivalentAddressGroup addressGroup = addressGroupList.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(mockLoadBalancerFactory).newLoadBalancer(helperCaptor.capture());
    Helper helper = helperCaptor.getValue();
    assertTrue(channel.inUseStateAggregator.isInUse());
    // Assume LoadBalancer has received an address, then create a subchannel.
    Subchannel subchannel = helper.createSubchannel(addressGroup, Attributes.EMPTY);
    subchannel.requestConnection();
    MockClientTransportInfo t0 = newTransports.poll();
    t0.listener.transportReady();
    SubchannelPicker mockPicker = mock(SubchannelPicker.class);
    when(mockPicker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withSubchannel(subchannel));
    helper.updatePicker(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) Matchers.anyString(org.mockito.Matchers.anyString) Test(org.junit.Test)

Example 8 with SubchannelPicker

use of io.grpc.LoadBalancer.SubchannelPicker in project grpc-java by grpc.

the class DelayedClientTransportTest method reprocess_newStreamRacesWithReprocess.

@Test
public void reprocess_newStreamRacesWithReprocess() throws Exception {
    final CyclicBarrier barrier = new CyclicBarrier(2);
    // In both phases, we only expect the first pickSubchannel() call to block on the barrier.
    final AtomicBoolean nextPickShouldWait = new AtomicBoolean(true);
    ///////// Phase 1: reprocess() twice with the same picker
    SubchannelPicker picker = mock(SubchannelPicker.class);
    doAnswer(new Answer<PickResult>() {

        @Override
        public PickResult answer(InvocationOnMock invocation) throws Throwable {
            if (nextPickShouldWait.compareAndSet(true, false)) {
                try {
                    barrier.await();
                    return PickResult.withNoResult();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return PickResult.withNoResult();
        }
    }).when(picker).pickSubchannel(any(PickSubchannelArgs.class));
    // Because there is no pending stream yet, it will do nothing but save the picker.
    delayedTransport.reprocess(picker);
    verify(picker, never()).pickSubchannel(any(PickSubchannelArgs.class));
    Thread sideThread = new Thread("sideThread") {

        @Override
        public void run() {
            // Will call pickSubchannel and wait on barrier
            delayedTransport.newStream(method, headers, callOptions, statsTraceCtx);
        }
    };
    sideThread.start();
    PickSubchannelArgsImpl args = new PickSubchannelArgsImpl(method, headers, callOptions);
    PickSubchannelArgsImpl args2 = new PickSubchannelArgsImpl(method, headers2, callOptions);
    // Is called from sideThread
    verify(picker, timeout(5000)).pickSubchannel(args);
    // Because stream has not been buffered (it's still stuck in newStream()), this will do nothing,
    // but incrementing the picker version.
    delayedTransport.reprocess(picker);
    verify(picker).pickSubchannel(args);
    // Now let the stuck newStream() through
    barrier.await(5, TimeUnit.SECONDS);
    sideThread.join(5000);
    assertFalse("sideThread should've exited", sideThread.isAlive());
    // newStream() detects that there has been a new picker while it's stuck, thus will pick again.
    verify(picker, times(2)).pickSubchannel(args);
    barrier.reset();
    nextPickShouldWait.set(true);
    ////////// Phase 2: reprocess() with a different picker
    // Create the second stream
    Thread sideThread2 = new Thread("sideThread2") {

        @Override
        public void run() {
            // Will call pickSubchannel and wait on barrier
            delayedTransport.newStream(method, headers2, callOptions, statsTraceCtx);
        }
    };
    sideThread2.start();
    // The second stream will see the first picker
    verify(picker, timeout(5000)).pickSubchannel(args2);
    // While the first stream won't use the first picker any more.
    verify(picker, times(2)).pickSubchannel(args);
    // Now use a different picker
    SubchannelPicker picker2 = mock(SubchannelPicker.class);
    when(picker2.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withNoResult());
    delayedTransport.reprocess(picker2);
    // The pending first stream uses the new picker
    verify(picker2).pickSubchannel(args);
    // The second stream is still pending in creation, doesn't use the new picker.
    verify(picker2, never()).pickSubchannel(args2);
    // Now let the second stream finish creation
    barrier.await(5, TimeUnit.SECONDS);
    sideThread2.join(5000);
    assertFalse("sideThread2 should've exited", sideThread2.isAlive());
    // The second stream should see the new picker
    verify(picker2, timeout(5000)).pickSubchannel(args2);
    // Wrapping up
    verify(picker, times(2)).pickSubchannel(args);
    verify(picker).pickSubchannel(args2);
    verify(picker2).pickSubchannel(args);
    verify(picker2).pickSubchannel(args);
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) SubchannelPicker(io.grpc.LoadBalancer.SubchannelPicker) InvocationOnMock(org.mockito.invocation.InvocationOnMock) PickResult(io.grpc.LoadBalancer.PickResult) PickSubchannelArgs(io.grpc.LoadBalancer.PickSubchannelArgs) CyclicBarrier(java.util.concurrent.CyclicBarrier) Test(org.junit.Test)

Example 9 with SubchannelPicker

use of io.grpc.LoadBalancer.SubchannelPicker in project grpc-java by grpc.

the class DelayedClientTransportTest method reprocess_NoPendingStream.

@Test
public void reprocess_NoPendingStream() {
    SubchannelPicker picker = mock(SubchannelPicker.class);
    SubchannelImpl subchannel = mock(SubchannelImpl.class);
    when(subchannel.obtainActiveTransport()).thenReturn(mockRealTransport);
    when(picker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withSubchannel(subchannel));
    when(mockRealTransport.newStream(any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class), same(statsTraceCtx))).thenReturn(mockRealStream);
    delayedTransport.reprocess(picker);
    verifyNoMoreInteractions(picker);
    verifyNoMoreInteractions(transportListener);
    // Though picker was not originally used, it will be saved and serve future streams.
    ClientStream stream = delayedTransport.newStream(method, headers, CallOptions.DEFAULT, statsTraceCtx);
    verify(picker).pickSubchannel(new PickSubchannelArgsImpl(method, headers, CallOptions.DEFAULT));
    verify(subchannel).obtainActiveTransport();
    assertSame(mockRealStream, stream);
}
Also used : SubchannelPicker(io.grpc.LoadBalancer.SubchannelPicker) Metadata(io.grpc.Metadata) PickSubchannelArgs(io.grpc.LoadBalancer.PickSubchannelArgs) CallOptions(io.grpc.CallOptions) MethodDescriptor(io.grpc.MethodDescriptor) Test(org.junit.Test)

Aggregations

SubchannelPicker (io.grpc.LoadBalancer.SubchannelPicker)9 PickSubchannelArgs (io.grpc.LoadBalancer.PickSubchannelArgs)8 Metadata (io.grpc.Metadata)6 Test (org.junit.Test)6 MockClientTransportInfo (io.grpc.internal.TestUtils.MockClientTransportInfo)4 Matchers.anyString (org.mockito.Matchers.anyString)4 Helper (io.grpc.LoadBalancer.Helper)3 PickResult (io.grpc.LoadBalancer.PickResult)3 Subchannel (io.grpc.LoadBalancer.Subchannel)3 MethodDescriptor (io.grpc.MethodDescriptor)3 Status (io.grpc.Status)3 SocketAddress (java.net.SocketAddress)3 CallOptions (io.grpc.CallOptions)2 EquivalentAddressGroup (io.grpc.EquivalentAddressGroup)2 InOrder (org.mockito.InOrder)2 Attributes (io.grpc.Attributes)1 ManagedChannel (io.grpc.ManagedChannel)1 ResolvedServerInfo (io.grpc.ResolvedServerInfo)1 ResolvedServerInfoGroup (io.grpc.ResolvedServerInfoGroup)1 CyclicBarrier (java.util.concurrent.CyclicBarrier)1