Search in sources :

Example 31 with SubchannelPicker

use of io.grpc.LoadBalancer.SubchannelPicker 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)

Example 32 with SubchannelPicker

use of io.grpc.LoadBalancer.SubchannelPicker 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);
}
Also used : PriorityChildConfig(io.grpc.xds.PriorityLoadBalancerProvider.PriorityLbConfig.PriorityChildConfig) PriorityLbConfig(io.grpc.xds.PriorityLoadBalancerProvider.PriorityLbConfig) Attributes(io.grpc.Attributes) PolicySelection(io.grpc.internal.ServiceConfigUtil.PolicySelection) Helper(io.grpc.LoadBalancer.Helper) SubchannelPicker(io.grpc.LoadBalancer.SubchannelPicker) EquivalentAddressGroup(io.grpc.EquivalentAddressGroup) Subchannel(io.grpc.LoadBalancer.Subchannel) PickResult(io.grpc.LoadBalancer.PickResult) PickSubchannelArgs(io.grpc.LoadBalancer.PickSubchannelArgs) Test(org.junit.Test)

Example 33 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);
    AbstractSubchannel subchannel = mock(AbstractSubchannel.class);
    when(subchannel.getInternalSubchannel()).thenReturn(mockInternalSubchannel);
    when(picker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withSubchannel(subchannel));
    when(mockRealTransport.newStream(any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class), ArgumentMatchers.<ClientStreamTracer[]>any())).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, tracers);
    verify(picker).pickSubchannel(new PickSubchannelArgsImpl(method, headers, CallOptions.DEFAULT));
    verify(mockInternalSubchannel).obtainActiveTransport();
    assertSame(mockRealStream, stream);
}
Also used : SubchannelPicker(io.grpc.LoadBalancer.SubchannelPicker) ClientStreamTracer(io.grpc.ClientStreamTracer) Metadata(io.grpc.Metadata) PickSubchannelArgs(io.grpc.LoadBalancer.PickSubchannelArgs) CallOptions(io.grpc.CallOptions) MethodDescriptor(io.grpc.MethodDescriptor) Test(org.junit.Test)

Example 34 with SubchannelPicker

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

the class DelayedClientTransportTest method newStream_racesWithReprocessIdleMode.

@Test
public void newStream_racesWithReprocessIdleMode() throws Exception {
    SubchannelPicker picker = new SubchannelPicker() {

        @Override
        public PickResult pickSubchannel(PickSubchannelArgs args) {
            // Assume entering idle mode raced with the pick
            delayedTransport.reprocess(null);
            // Act like IDLE LB
            return PickResult.withNoResult();
        }
    };
    // Because there is no pending stream yet, it will do nothing but save the picker.
    delayedTransport.reprocess(picker);
    ClientStream stream = delayedTransport.newStream(method, headers, callOptions, tracers);
    stream.start(streamListener);
    assertTrue(delayedTransport.hasPendingStreams());
    verify(transportListener).transportInUse(true);
}
Also used : SubchannelPicker(io.grpc.LoadBalancer.SubchannelPicker) PickSubchannelArgs(io.grpc.LoadBalancer.PickSubchannelArgs) Test(org.junit.Test)

Example 35 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
        @SuppressWarnings("CatchAndPrintStackTrace")
        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, tracers);
        }
    };
    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, tracers);
        }
    };
    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 : CyclicBarrier(java.util.concurrent.CyclicBarrier) 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) Test(org.junit.Test)

Aggregations

SubchannelPicker (io.grpc.LoadBalancer.SubchannelPicker)50 Test (org.junit.Test)44 PickSubchannelArgs (io.grpc.LoadBalancer.PickSubchannelArgs)21 Helper (io.grpc.LoadBalancer.Helper)19 Metadata (io.grpc.Metadata)17 Subchannel (io.grpc.LoadBalancer.Subchannel)15 LoadBalancer (io.grpc.LoadBalancer)13 EquivalentAddressGroup (io.grpc.EquivalentAddressGroup)12 PickResult (io.grpc.LoadBalancer.PickResult)11 InOrder (org.mockito.InOrder)11 CreateSubchannelArgs (io.grpc.LoadBalancer.CreateSubchannelArgs)8 MockClientTransportInfo (io.grpc.internal.TestUtils.MockClientTransportInfo)7 CallOptions (io.grpc.CallOptions)6 ClientStreamTracer (io.grpc.ClientStreamTracer)6 Status (io.grpc.Status)6 PickSubchannelArgsImpl (io.grpc.internal.PickSubchannelArgsImpl)6 Attributes (io.grpc.Attributes)4 UnsupportedClientTransportFactoryBuilder (io.grpc.internal.ManagedChannelImplBuilder.UnsupportedClientTransportFactoryBuilder)4 ForwardingSubchannel (io.grpc.util.ForwardingSubchannel)4 ChannelLogger (io.grpc.ChannelLogger)3