Search in sources :

Example 11 with Subchannel

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

the class RoundRobinLoadBalancerTest method nameResolutionErrorWithActiveChannels.

@Test
public void nameResolutionErrorWithActiveChannels() throws Exception {
    final Subchannel readySubchannel = subchannels.values().iterator().next();
    loadBalancer.handleResolvedAddresses(Lists.newArrayList(servers.keySet()), affinity);
    loadBalancer.handleSubchannelState(readySubchannel, ConnectivityStateInfo.forNonError(READY));
    loadBalancer.handleNameResolutionError(Status.NOT_FOUND.withDescription("nameResolutionError"));
    verify(mockHelper, times(3)).createSubchannel(any(EquivalentAddressGroup.class), any(Attributes.class));
    verify(mockHelper, times(3)).updatePicker(pickerCaptor.capture());
    LoadBalancer.PickResult pickResult = pickerCaptor.getValue().pickSubchannel(mockArgs);
    assertEquals(readySubchannel, pickResult.getSubchannel());
    assertEquals(Status.OK.getCode(), pickResult.getStatus().getCode());
    LoadBalancer.PickResult pickResult2 = pickerCaptor.getValue().pickSubchannel(mockArgs);
    assertEquals(readySubchannel, pickResult2.getSubchannel());
    verifyNoMoreInteractions(mockHelper);
}
Also used : Subchannel(io.grpc.LoadBalancer.Subchannel) EquivalentAddressGroup(io.grpc.EquivalentAddressGroup) Attributes(io.grpc.Attributes) RoundRobinLoadBalancer(io.grpc.util.RoundRobinLoadBalancerFactory.RoundRobinLoadBalancer) LoadBalancer(io.grpc.LoadBalancer) Test(org.junit.Test)

Example 12 with Subchannel

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

the class GrpclbLoadBalancerTest method roundRobinPicker.

@Test
public void roundRobinPicker() {
    Subchannel subchannel = mock(Subchannel.class);
    RoundRobinEntry r1 = new RoundRobinEntry(Status.UNAVAILABLE.withDescription("Just error"));
    RoundRobinEntry r2 = new RoundRobinEntry(subchannel, "LBTOKEN0001");
    RoundRobinEntry r3 = new RoundRobinEntry(subchannel, "LBTOKEN0002");
    List<RoundRobinEntry> list = Arrays.asList(r1, r2, r3);
    RoundRobinPicker picker = new RoundRobinPicker(list);
    PickSubchannelArgs args1 = mock(PickSubchannelArgs.class);
    Metadata headers1 = new Metadata();
    when(args1.getHeaders()).thenReturn(headers1);
    assertSame(r1.result, picker.pickSubchannel(args1));
    verify(args1).getHeaders();
    assertFalse(headers1.containsKey(GrpclbLoadBalancer.TOKEN_KEY));
    PickSubchannelArgs args2 = mock(PickSubchannelArgs.class);
    Metadata headers2 = new Metadata();
    // The existing token on the headers will be replaced
    headers2.put(GrpclbLoadBalancer.TOKEN_KEY, "LBTOKEN__OLD");
    when(args2.getHeaders()).thenReturn(headers2);
    assertSame(r2.result, picker.pickSubchannel(args2));
    verify(args2).getHeaders();
    assertThat(headers2.getAll(GrpclbLoadBalancer.TOKEN_KEY)).containsExactly("LBTOKEN0001");
    PickSubchannelArgs args3 = mock(PickSubchannelArgs.class);
    Metadata headers3 = new Metadata();
    when(args3.getHeaders()).thenReturn(headers3);
    assertSame(r3.result, picker.pickSubchannel(args3));
    verify(args3).getHeaders();
    assertThat(headers3.getAll(GrpclbLoadBalancer.TOKEN_KEY)).containsExactly("LBTOKEN0002");
    PickSubchannelArgs args4 = mock(PickSubchannelArgs.class);
    Metadata headers4 = new Metadata();
    when(args4.getHeaders()).thenReturn(headers4);
    assertSame(r1.result, picker.pickSubchannel(args4));
    verify(args4).getHeaders();
    assertFalse(headers4.containsKey(GrpclbLoadBalancer.TOKEN_KEY));
    verify(subchannel, never()).getAttributes();
}
Also used : RoundRobinPicker(io.grpc.grpclb.GrpclbLoadBalancer.RoundRobinPicker) Subchannel(io.grpc.LoadBalancer.Subchannel) Metadata(io.grpc.Metadata) PickSubchannelArgs(io.grpc.LoadBalancer.PickSubchannelArgs) RoundRobinEntry(io.grpc.grpclb.GrpclbLoadBalancer.RoundRobinEntry) Test(org.junit.Test)

Example 13 with Subchannel

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

the class GrpclbLoadBalancerTest method tearDown.

@After
public void tearDown() {
    try {
        if (balancer != null) {
            channelExecutor.execute(new Runnable() {

                @Override
                public void run() {
                    balancer.shutdown();
                }
            });
        }
        for (ManagedChannel channel : oobChannelTracker) {
            assertTrue(channel + " is shutdown", channel.isShutdown());
            // balancer should have closed the LB stream, terminating the OOB channel.
            assertTrue(channel + " is terminated", channel.isTerminated());
        }
        for (Subchannel subchannel : subchannelTracker) {
            verify(subchannel).shutdown();
        }
    } finally {
        if (fakeLbServer != null) {
            fakeLbServer.shutdownNow();
        }
    }
}
Also used : Subchannel(io.grpc.LoadBalancer.Subchannel) ManagedChannel(io.grpc.ManagedChannel) After(org.junit.After)

Example 14 with Subchannel

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

the class GrpclbLoadBalancerTest method grpclbWorking.

@Test
public void grpclbWorking() {
    InOrder inOrder = inOrder(helper);
    List<ResolvedServerInfoGroup> grpclbResolutionList = createResolvedServerInfoGroupList(true, true);
    Attributes grpclbResolutionAttrs = Attributes.newBuilder().set(GrpclbConstants.ATTR_LB_POLICY, LbPolicy.GRPCLB).build();
    deliverResolvedAddresses(grpclbResolutionList, grpclbResolutionAttrs);
    assertSame(LbPolicy.GRPCLB, balancer.getLbPolicy());
    assertNull(balancer.getDelegate());
    verify(helper).createOobChannel(eq(grpclbResolutionList.get(0).toEquivalentAddressGroup()), eq(lbAuthority(0)));
    assertEquals(1, fakeOobChannels.size());
    ManagedChannel oobChannel = fakeOobChannels.poll();
    verify(mockLbService).balanceLoad(lbResponseObserverCaptor.capture());
    StreamObserver<LoadBalanceResponse> lbResponseObserver = lbResponseObserverCaptor.getValue();
    // Simulate receiving LB response
    List<ServerEntry> backends1 = Arrays.asList(new ServerEntry("127.0.0.1", 2000, "token0001"), new ServerEntry("127.0.0.1", 2010, "token0002"));
    inOrder.verify(helper, never()).updatePicker(any(SubchannelPicker.class));
    lbResponseObserver.onNext(buildInitialResponse());
    lbResponseObserver.onNext(buildLbResponse(backends1));
    inOrder.verify(helper).createSubchannel(eq(new EquivalentAddressGroup(backends1.get(0).addr)), any(Attributes.class));
    inOrder.verify(helper).createSubchannel(eq(new EquivalentAddressGroup(backends1.get(1).addr)), any(Attributes.class));
    assertEquals(2, mockSubchannels.size());
    Subchannel subchannel1 = mockSubchannels.poll();
    Subchannel subchannel2 = mockSubchannels.poll();
    verify(subchannel1).requestConnection();
    verify(subchannel2).requestConnection();
    assertEquals(new EquivalentAddressGroup(backends1.get(0).addr), subchannel1.getAddresses());
    assertEquals(new EquivalentAddressGroup(backends1.get(1).addr), subchannel2.getAddresses());
    // Before any subchannel is READY, a buffer picker will be provided
    inOrder.verify(helper).updatePicker(same(GrpclbLoadBalancer.BUFFER_PICKER));
    deliverSubchannelState(subchannel1, ConnectivityStateInfo.forNonError(CONNECTING));
    deliverSubchannelState(subchannel2, ConnectivityStateInfo.forNonError(CONNECTING));
    inOrder.verify(helper, times(2)).updatePicker(same(GrpclbLoadBalancer.BUFFER_PICKER));
    // Let subchannels be connected
    deliverSubchannelState(subchannel2, ConnectivityStateInfo.forNonError(READY));
    inOrder.verify(helper).updatePicker(pickerCaptor.capture());
    RoundRobinPicker picker1 = (RoundRobinPicker) pickerCaptor.getValue();
    assertThat(picker1.list).containsExactly(new RoundRobinEntry(subchannel2, "token0002"));
    deliverSubchannelState(subchannel1, ConnectivityStateInfo.forNonError(READY));
    inOrder.verify(helper).updatePicker(pickerCaptor.capture());
    RoundRobinPicker picker2 = (RoundRobinPicker) pickerCaptor.getValue();
    assertThat(picker2.list).containsExactly(new RoundRobinEntry(subchannel1, "token0001"), new RoundRobinEntry(subchannel2, "token0002")).inOrder();
    // Disconnected subchannels
    verify(subchannel1).requestConnection();
    deliverSubchannelState(subchannel1, ConnectivityStateInfo.forNonError(IDLE));
    verify(subchannel1, times(2)).requestConnection();
    inOrder.verify(helper).updatePicker(pickerCaptor.capture());
    RoundRobinPicker picker3 = (RoundRobinPicker) pickerCaptor.getValue();
    assertThat(picker3.list).containsExactly(new RoundRobinEntry(subchannel2, "token0002"));
    deliverSubchannelState(subchannel1, ConnectivityStateInfo.forNonError(CONNECTING));
    inOrder.verify(helper).updatePicker(pickerCaptor.capture());
    RoundRobinPicker picker4 = (RoundRobinPicker) pickerCaptor.getValue();
    assertThat(picker4.list).containsExactly(new RoundRobinEntry(subchannel2, "token0002"));
    // As long as there is at least one READY subchannel, round robin will work.
    Status error1 = Status.UNAVAILABLE.withDescription("error1");
    deliverSubchannelState(subchannel1, ConnectivityStateInfo.forTransientFailure(error1));
    inOrder.verify(helper).updatePicker(pickerCaptor.capture());
    RoundRobinPicker picker5 = (RoundRobinPicker) pickerCaptor.getValue();
    assertThat(picker5.list).containsExactly(new RoundRobinEntry(subchannel2, "token0002"));
    // If no subchannel is READY, will propagate an error from an arbitrary subchannel (but here
    // only subchannel1 has error).
    verify(subchannel2).requestConnection();
    deliverSubchannelState(subchannel2, ConnectivityStateInfo.forNonError(IDLE));
    verify(subchannel2, times(2)).requestConnection();
    inOrder.verify(helper).updatePicker(pickerCaptor.capture());
    ErrorPicker picker6 = (ErrorPicker) pickerCaptor.getValue();
    assertNull(picker6.result.getSubchannel());
    assertSame(error1, picker6.result.getStatus());
    // Update backends, with a drop entry
    List<ServerEntry> backends2 = Arrays.asList(// New address
    new ServerEntry("127.0.0.1", 2030, "token0003"), // drop
    null, // Existing address with token changed
    new ServerEntry("127.0.0.1", 2010, "token0004"), // New address appearing second time
    new ServerEntry("127.0.0.1", 2030, "token0005"));
    verify(subchannel1, never()).shutdown();
    lbResponseObserver.onNext(buildLbResponse(backends2));
    // not in backends2, closed
    verify(subchannel1).shutdown();
    // backends2[2], will be kept
    verify(subchannel2, never()).shutdown();
    inOrder.verify(helper, never()).createSubchannel(eq(new EquivalentAddressGroup(backends2.get(2).addr)), any(Attributes.class));
    inOrder.verify(helper).createSubchannel(eq(new EquivalentAddressGroup(backends2.get(0).addr)), any(Attributes.class));
    assertEquals(1, mockSubchannels.size());
    Subchannel subchannel3 = mockSubchannels.poll();
    verify(subchannel3).requestConnection();
    assertEquals(new EquivalentAddressGroup(backends2.get(0).addr), subchannel3.getAddresses());
    inOrder.verify(helper).updatePicker(pickerCaptor.capture());
    RoundRobinPicker picker7 = (RoundRobinPicker) pickerCaptor.getValue();
    assertThat(picker7.list).containsExactly(GrpclbLoadBalancer.DROP_ENTRY);
    // State updates on obsolete subchannel1 will have no effect
    deliverSubchannelState(subchannel1, ConnectivityStateInfo.forNonError(READY));
    deliverSubchannelState(subchannel1, ConnectivityStateInfo.forTransientFailure(Status.UNAVAILABLE));
    deliverSubchannelState(subchannel1, ConnectivityStateInfo.forNonError(SHUTDOWN));
    inOrder.verifyNoMoreInteractions();
    deliverSubchannelState(subchannel3, ConnectivityStateInfo.forNonError(READY));
    inOrder.verify(helper).updatePicker(pickerCaptor.capture());
    RoundRobinPicker picker8 = (RoundRobinPicker) pickerCaptor.getValue();
    // subchannel2 is still IDLE, thus not in the active list
    assertThat(picker8.list).containsExactly(new RoundRobinEntry(subchannel3, "token0003"), GrpclbLoadBalancer.DROP_ENTRY, new RoundRobinEntry(subchannel3, "token0005")).inOrder();
    // subchannel2 becomes READY and makes it into the list
    deliverSubchannelState(subchannel2, ConnectivityStateInfo.forNonError(READY));
    inOrder.verify(helper).updatePicker(pickerCaptor.capture());
    RoundRobinPicker picker9 = (RoundRobinPicker) pickerCaptor.getValue();
    assertThat(picker9.list).containsExactly(new RoundRobinEntry(subchannel3, "token0003"), GrpclbLoadBalancer.DROP_ENTRY, new RoundRobinEntry(subchannel2, "token0004"), new RoundRobinEntry(subchannel3, "token0005")).inOrder();
    verify(subchannel3, never()).shutdown();
    assertFalse(oobChannel.isShutdown());
    assertEquals(1, lbRequestObservers.size());
    verify(lbRequestObservers.peek(), never()).onCompleted();
    verify(lbRequestObservers.peek(), never()).onError(any(Throwable.class));
}
Also used : Status(io.grpc.Status) ErrorPicker(io.grpc.grpclb.GrpclbLoadBalancer.ErrorPicker) InOrder(org.mockito.InOrder) Attributes(io.grpc.Attributes) ResolvedServerInfoGroup(io.grpc.ResolvedServerInfoGroup) SubchannelPicker(io.grpc.LoadBalancer.SubchannelPicker) RoundRobinPicker(io.grpc.grpclb.GrpclbLoadBalancer.RoundRobinPicker) EquivalentAddressGroup(io.grpc.EquivalentAddressGroup) Subchannel(io.grpc.LoadBalancer.Subchannel) ManagedChannel(io.grpc.ManagedChannel) RoundRobinEntry(io.grpc.grpclb.GrpclbLoadBalancer.RoundRobinEntry) Test(org.junit.Test)

Example 15 with Subchannel

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

the class RoundRobinLoadBalancerTest method pickAfterResolvedUpdatedHosts.

@Test
public void pickAfterResolvedUpdatedHosts() throws Exception {
    Subchannel removedSubchannel = mock(Subchannel.class);
    Subchannel oldSubchannel = mock(Subchannel.class);
    Subchannel newSubchannel = mock(Subchannel.class);
    for (Subchannel subchannel : Lists.newArrayList(removedSubchannel, oldSubchannel, newSubchannel)) {
        when(subchannel.getAttributes()).thenReturn(Attributes.newBuilder().set(STATE_INFO, new AtomicReference<ConnectivityStateInfo>(ConnectivityStateInfo.forNonError(READY))).build());
    }
    FakeSocketAddress removedAddr = new FakeSocketAddress("removed");
    FakeSocketAddress oldAddr = new FakeSocketAddress("old");
    FakeSocketAddress newAddr = new FakeSocketAddress("new");
    final Map<EquivalentAddressGroup, Subchannel> subchannels2 = Maps.newHashMap();
    subchannels2.put(new EquivalentAddressGroup(removedAddr), removedSubchannel);
    subchannels2.put(new EquivalentAddressGroup(oldAddr), oldSubchannel);
    List<ResolvedServerInfoGroup> currentServers = Lists.newArrayList(ResolvedServerInfoGroup.builder().add(new ResolvedServerInfo(removedAddr)).add(new ResolvedServerInfo(oldAddr)).build());
    doAnswer(new Answer<Subchannel>() {

        @Override
        public Subchannel answer(InvocationOnMock invocation) throws Throwable {
            Object[] args = invocation.getArguments();
            return subchannels2.get(args[0]);
        }
    }).when(mockHelper).createSubchannel(any(EquivalentAddressGroup.class), any(Attributes.class));
    loadBalancer.handleResolvedAddresses(currentServers, affinity);
    InOrder inOrder = inOrder(mockHelper);
    inOrder.verify(mockHelper).updatePicker(pickerCaptor.capture());
    Picker picker = pickerCaptor.getValue();
    assertNull(picker.getStatus());
    assertThat(picker.getList()).containsExactly(removedSubchannel, oldSubchannel);
    verify(removedSubchannel, times(1)).requestConnection();
    verify(oldSubchannel, times(1)).requestConnection();
    assertThat(loadBalancer.getSubchannels()).containsExactly(removedSubchannel, oldSubchannel);
    subchannels2.clear();
    subchannels2.put(new EquivalentAddressGroup(oldAddr), oldSubchannel);
    subchannels2.put(new EquivalentAddressGroup(newAddr), newSubchannel);
    List<ResolvedServerInfoGroup> latestServers = Lists.newArrayList(ResolvedServerInfoGroup.builder().add(new ResolvedServerInfo(oldAddr)).add(new ResolvedServerInfo(newAddr)).build());
    loadBalancer.handleResolvedAddresses(latestServers, affinity);
    verify(newSubchannel, times(1)).requestConnection();
    verify(removedSubchannel, times(1)).shutdown();
    assertThat(loadBalancer.getSubchannels()).containsExactly(oldSubchannel, newSubchannel);
    verify(mockHelper, times(3)).createSubchannel(any(EquivalentAddressGroup.class), any(Attributes.class));
    inOrder.verify(mockHelper).updatePicker(pickerCaptor.capture());
    picker = pickerCaptor.getValue();
    assertNull(picker.getStatus());
    assertThat(picker.getList()).containsExactly(oldSubchannel, newSubchannel);
    verifyNoMoreInteractions(mockHelper);
}
Also used : InOrder(org.mockito.InOrder) Attributes(io.grpc.Attributes) ResolvedServerInfo(io.grpc.ResolvedServerInfo) ResolvedServerInfoGroup(io.grpc.ResolvedServerInfoGroup) ConnectivityStateInfo(io.grpc.ConnectivityStateInfo) Subchannel(io.grpc.LoadBalancer.Subchannel) EquivalentAddressGroup(io.grpc.EquivalentAddressGroup) InvocationOnMock(org.mockito.invocation.InvocationOnMock) Picker(io.grpc.util.RoundRobinLoadBalancerFactory.Picker) Test(org.junit.Test)

Aggregations

Subchannel (io.grpc.LoadBalancer.Subchannel)22 Test (org.junit.Test)18 Attributes (io.grpc.Attributes)8 MockClientTransportInfo (io.grpc.internal.TestUtils.MockClientTransportInfo)8 SocketAddress (java.net.SocketAddress)8 Metadata (io.grpc.Metadata)7 InOrder (org.mockito.InOrder)7 Matchers.anyString (org.mockito.Matchers.anyString)7 EquivalentAddressGroup (io.grpc.EquivalentAddressGroup)6 PickSubchannelArgs (io.grpc.LoadBalancer.PickSubchannelArgs)6 ResolvedServerInfoGroup (io.grpc.ResolvedServerInfoGroup)5 Status (io.grpc.Status)5 SubchannelPicker (io.grpc.LoadBalancer.SubchannelPicker)4 ResolvedServerInfo (io.grpc.ResolvedServerInfo)4 Picker (io.grpc.util.RoundRobinLoadBalancerFactory.Picker)4 CallOptions (io.grpc.CallOptions)3 MethodDescriptor (io.grpc.MethodDescriptor)3 InvocationOnMock (org.mockito.invocation.InvocationOnMock)3 ConnectivityStateInfo (io.grpc.ConnectivityStateInfo)2 Helper (io.grpc.LoadBalancer.Helper)2