Search in sources :

Example 6 with EquivalentAddressGroup

use of io.grpc.EquivalentAddressGroup in project grpc-java by grpc.

the class GrpclbLoadBalancer method handleResolvedAddresses.

@Override
public void handleResolvedAddresses(List<ResolvedServerInfoGroup> updatedServers, Attributes attributes) {
    LbPolicy newLbPolicy = attributes.get(GrpclbConstants.ATTR_LB_POLICY);
    // LB addresses and backend addresses are treated separately
    List<LbAddressGroup> newLbAddressGroups = new ArrayList<LbAddressGroup>();
    List<ResolvedServerInfoGroup> newBackendServerInfoGroups = new ArrayList<ResolvedServerInfoGroup>();
    for (ResolvedServerInfoGroup serverInfoGroup : updatedServers) {
        String lbAddrAuthority = serverInfoGroup.getAttributes().get(GrpclbConstants.ATTR_LB_ADDR_AUTHORITY);
        EquivalentAddressGroup eag = serverInfoGroup.toEquivalentAddressGroup();
        if (lbAddrAuthority != null) {
            newLbAddressGroups.add(new LbAddressGroup(eag, lbAddrAuthority));
        } else {
            newBackendServerInfoGroups.add(serverInfoGroup);
        }
    }
    if (newBackendServerInfoGroups.isEmpty()) {
        // handleResolvedAddresses()'s javadoc has guaranteed updatedServers is never empty.
        checkState(!newLbAddressGroups.isEmpty(), "No backend address nor LB address.  updatedServers=%s", updatedServers);
        if (newLbPolicy != LbPolicy.GRPCLB) {
            newLbPolicy = LbPolicy.GRPCLB;
            logger.log(Level.FINE, "[{0}] Switching to GRPCLB because all addresses are balancers", logId);
        }
    }
    if (newLbPolicy == null) {
        logger.log(Level.FINE, "[{0}] New config missing policy. Using PICK_FIRST", logId);
        newLbPolicy = LbPolicy.PICK_FIRST;
    }
    // Switch LB policy if requested
    if (newLbPolicy != lbPolicy) {
        shutdownDelegate();
        shutdownLbComm();
        lbAddressGroups = null;
        currentLbIndex = 0;
        switch(newLbPolicy) {
            case PICK_FIRST:
                delegate = checkNotNull(pickFirstBalancerFactory.newLoadBalancer(helper), "pickFirstBalancerFactory.newLoadBalancer()");
                break;
            case ROUND_ROBIN:
                delegate = checkNotNull(roundRobinBalancerFactory.newLoadBalancer(helper), "roundRobinBalancerFactory.newLoadBalancer()");
                break;
            default:
        }
    }
    lbPolicy = newLbPolicy;
    // Consume the new addresses
    switch(lbPolicy) {
        case PICK_FIRST:
        case ROUND_ROBIN:
            checkNotNull(delegate, "delegate should not be null. newLbPolicy=" + newLbPolicy);
            delegate.handleResolvedAddresses(newBackendServerInfoGroups, attributes);
            break;
        case GRPCLB:
            if (newLbAddressGroups.isEmpty()) {
                shutdownLbComm();
                lbAddressGroups = null;
                handleGrpclbError(Status.UNAVAILABLE.withDescription("NameResolver returned no LB address while asking for GRPCLB"));
            } else {
                // See if the currently used LB server is in the new list.
                int newIndexOfCurrentLb = -1;
                if (lbAddressGroups != null) {
                    LbAddressGroup currentLb = lbAddressGroups.get(currentLbIndex);
                    newIndexOfCurrentLb = newLbAddressGroups.indexOf(currentLb);
                }
                lbAddressGroups = newLbAddressGroups;
                if (newIndexOfCurrentLb == -1) {
                    shutdownLbComm();
                    currentLbIndex = 0;
                    startLbComm();
                } else {
                    // Current LB is still in the list, calibrate index.
                    currentLbIndex = newIndexOfCurrentLb;
                }
            }
            break;
        default:
    }
}
Also used : LbPolicy(io.grpc.grpclb.GrpclbConstants.LbPolicy) EquivalentAddressGroup(io.grpc.EquivalentAddressGroup) ArrayList(java.util.ArrayList) ResolvedServerInfoGroup(io.grpc.ResolvedServerInfoGroup)

Example 7 with EquivalentAddressGroup

use of io.grpc.EquivalentAddressGroup 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 8 with EquivalentAddressGroup

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

Example 9 with EquivalentAddressGroup

use of io.grpc.EquivalentAddressGroup 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 10 with EquivalentAddressGroup

use of io.grpc.EquivalentAddressGroup in project grpc-java by grpc.

the class InternalSubchannelTest method createInternalSubchannel.

private void createInternalSubchannel(SocketAddress... addrs) {
    addressGroup = new EquivalentAddressGroup(Arrays.asList(addrs));
    internalSubchannel = new InternalSubchannel(addressGroup, AUTHORITY, USER_AGENT, mockBackoffPolicyProvider, mockTransportFactory, fakeClock.getScheduledExecutorService(), fakeClock.getStopwatchSupplier(), channelExecutor, mockInternalSubchannelCallback);
}
Also used : EquivalentAddressGroup(io.grpc.EquivalentAddressGroup)

Aggregations

EquivalentAddressGroup (io.grpc.EquivalentAddressGroup)10 Attributes (io.grpc.Attributes)7 ResolvedServerInfoGroup (io.grpc.ResolvedServerInfoGroup)6 Test (org.junit.Test)6 Subchannel (io.grpc.LoadBalancer.Subchannel)4 Status (io.grpc.Status)4 ErrorPicker (io.grpc.grpclb.GrpclbLoadBalancer.ErrorPicker)4 InOrder (org.mockito.InOrder)4 SubchannelPicker (io.grpc.LoadBalancer.SubchannelPicker)3 PickSubchannelArgs (io.grpc.LoadBalancer.PickSubchannelArgs)2 ManagedChannel (io.grpc.ManagedChannel)2 ResolvedServerInfo (io.grpc.ResolvedServerInfo)2 InvocationOnMock (org.mockito.invocation.InvocationOnMock)2 ConnectivityStateInfo (io.grpc.ConnectivityStateInfo)1 Helper (io.grpc.LoadBalancer.Helper)1 PickResult (io.grpc.LoadBalancer.PickResult)1 Metadata (io.grpc.Metadata)1 LbPolicy (io.grpc.grpclb.GrpclbConstants.LbPolicy)1 RoundRobinEntry (io.grpc.grpclb.GrpclbLoadBalancer.RoundRobinEntry)1 RoundRobinPicker (io.grpc.grpclb.GrpclbLoadBalancer.RoundRobinPicker)1