Search in sources :

Example 11 with ResolvedServerInfoGroup

use of io.grpc.ResolvedServerInfoGroup 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 12 with ResolvedServerInfoGroup

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

the class GrpclbLoadBalancerTest method switchPolicy.

@SuppressWarnings("unchecked")
@Test
public void switchPolicy() {
    // Go to GRPCLB first
    List<ResolvedServerInfoGroup> grpclbResolutionList = createResolvedServerInfoGroupList(true, false, 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());
    // Switch to PICK_FIRST
    List<ResolvedServerInfoGroup> pickFirstResolutionList = createResolvedServerInfoGroupList(true, false, true);
    Attributes pickFirstResolutionAttrs = Attributes.newBuilder().set(GrpclbConstants.ATTR_LB_POLICY, LbPolicy.PICK_FIRST).build();
    verify(pickFirstBalancerFactory, never()).newLoadBalancer(any(Helper.class));
    assertEquals(1, lbRequestObservers.size());
    StreamObserver<LoadBalanceRequest> lbRequestObserver = lbRequestObservers.poll();
    verify(lbRequestObserver, never()).onCompleted();
    assertFalse(oobChannel.isShutdown());
    deliverResolvedAddresses(pickFirstResolutionList, pickFirstResolutionAttrs);
    verify(pickFirstBalancerFactory).newLoadBalancer(same(helper));
    // Only non-LB addresses are passed to the delegate
    verify(pickFirstBalancer).handleResolvedAddresses(eq(Arrays.asList(pickFirstResolutionList.get(1))), same(pickFirstResolutionAttrs));
    assertSame(LbPolicy.PICK_FIRST, balancer.getLbPolicy());
    assertSame(pickFirstBalancer, balancer.getDelegate());
    // GRPCLB connection is closed
    verify(lbRequestObserver).onCompleted();
    assertTrue(oobChannel.isShutdown());
    // Switch to ROUND_ROBIN
    List<ResolvedServerInfoGroup> roundRobinResolutionList = createResolvedServerInfoGroupList(true, false, false);
    Attributes roundRobinResolutionAttrs = Attributes.newBuilder().set(GrpclbConstants.ATTR_LB_POLICY, LbPolicy.ROUND_ROBIN).build();
    verify(roundRobinBalancerFactory, never()).newLoadBalancer(any(Helper.class));
    deliverResolvedAddresses(roundRobinResolutionList, roundRobinResolutionAttrs);
    verify(roundRobinBalancerFactory).newLoadBalancer(same(helper));
    // Only non-LB addresses are passed to the delegate
    verify(roundRobinBalancer).handleResolvedAddresses(eq(roundRobinResolutionList.subList(1, 3)), same(roundRobinResolutionAttrs));
    assertSame(LbPolicy.ROUND_ROBIN, balancer.getLbPolicy());
    assertSame(roundRobinBalancer, balancer.getDelegate());
    // Special case: if all addresses are loadbalancers, use GRPCLB no matter what the NameResolver
    // says.
    grpclbResolutionList = createResolvedServerInfoGroupList(true, true, true);
    grpclbResolutionAttrs = Attributes.newBuilder().set(GrpclbConstants.ATTR_LB_POLICY, LbPolicy.PICK_FIRST).build();
    deliverResolvedAddresses(grpclbResolutionList, grpclbResolutionAttrs);
    assertSame(LbPolicy.GRPCLB, balancer.getLbPolicy());
    assertNull(balancer.getDelegate());
    verify(helper, times(2)).createOobChannel(eq(grpclbResolutionList.get(0).toEquivalentAddressGroup()), eq(lbAuthority(0)));
    verify(helper, times(2)).createOobChannel(any(EquivalentAddressGroup.class), any(String.class));
    assertEquals(1, fakeOobChannels.size());
    oobChannel = fakeOobChannels.poll();
    verify(mockLbService, times(2)).balanceLoad(lbResponseObserverCaptor.capture());
    // Special case: PICK_FIRST is the default
    pickFirstResolutionList = createResolvedServerInfoGroupList(true, false, false);
    pickFirstResolutionAttrs = Attributes.EMPTY;
    verify(pickFirstBalancerFactory).newLoadBalancer(any(Helper.class));
    assertFalse(oobChannel.isShutdown());
    deliverResolvedAddresses(pickFirstResolutionList, pickFirstResolutionAttrs);
    verify(pickFirstBalancerFactory, times(2)).newLoadBalancer(same(helper));
    // Only non-LB addresses are passed to the delegate
    verify(pickFirstBalancer).handleResolvedAddresses(eq(pickFirstResolutionList.subList(1, 3)), same(pickFirstResolutionAttrs));
    assertSame(LbPolicy.PICK_FIRST, balancer.getLbPolicy());
    assertSame(pickFirstBalancer, balancer.getDelegate());
    // GRPCLB connection is closed
    assertTrue(oobChannel.isShutdown());
}
Also used : Helper(io.grpc.LoadBalancer.Helper) EquivalentAddressGroup(io.grpc.EquivalentAddressGroup) Attributes(io.grpc.Attributes) ManagedChannel(io.grpc.ManagedChannel) ResolvedServerInfoGroup(io.grpc.ResolvedServerInfoGroup) ByteString(com.google.protobuf.ByteString) Test(org.junit.Test)

Example 13 with ResolvedServerInfoGroup

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

the class GrpclbLoadBalancerTest method createResolvedServerInfoGroupList.

private static List<ResolvedServerInfoGroup> createResolvedServerInfoGroupList(boolean... isLb) {
    ArrayList<ResolvedServerInfoGroup> list = new ArrayList<ResolvedServerInfoGroup>();
    for (int i = 0; i < isLb.length; i++) {
        SocketAddress addr = new FakeSocketAddress("fake-address-" + i);
        ResolvedServerInfoGroup serverInfoGroup = ResolvedServerInfoGroup.builder(isLb[i] ? Attributes.newBuilder().set(GrpclbConstants.ATTR_LB_ADDR_AUTHORITY, lbAuthority(i)).build() : Attributes.EMPTY).add(new ResolvedServerInfo(addr)).build();
        list.add(serverInfoGroup);
    }
    return list;
}
Also used : ArrayList(java.util.ArrayList) ResolvedServerInfoGroup(io.grpc.ResolvedServerInfoGroup) ResolvedServerInfo(io.grpc.ResolvedServerInfo) SocketAddress(java.net.SocketAddress) InetSocketAddress(java.net.InetSocketAddress)

Example 14 with ResolvedServerInfoGroup

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

the class GrpclbLoadBalancerTest method delegatingRoundRobinThenNameResolutionFails.

@Test
public void delegatingRoundRobinThenNameResolutionFails() {
    List<ResolvedServerInfoGroup> resolvedServers = createResolvedServerInfoGroupList(false, false);
    Attributes resolutionAttrs = Attributes.newBuilder().set(RESOLUTION_ATTR, "yeah").set(GrpclbConstants.ATTR_LB_POLICY, LbPolicy.ROUND_ROBIN).build();
    deliverResolvedAddresses(resolvedServers, resolutionAttrs);
    verify(roundRobinBalancerFactory).newLoadBalancer(helper);
    verify(roundRobinBalancer).handleResolvedAddresses(resolvedServers, resolutionAttrs);
    // Then let name resolution fail.  The error will be passed directly to the delegate.
    Status error = Status.NOT_FOUND.withDescription("www.google.com not found");
    deliverNameResolutionError(error);
    verify(roundRobinBalancer).handleNameResolutionError(error);
    verify(helper, never()).updatePicker(any(SubchannelPicker.class));
    verifyNoMoreInteractions(pickFirstBalancerFactory);
    verifyNoMoreInteractions(pickFirstBalancer);
}
Also used : Status(io.grpc.Status) SubchannelPicker(io.grpc.LoadBalancer.SubchannelPicker) Attributes(io.grpc.Attributes) ResolvedServerInfoGroup(io.grpc.ResolvedServerInfoGroup) Test(org.junit.Test)

Example 15 with ResolvedServerInfoGroup

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

Aggregations

ResolvedServerInfoGroup (io.grpc.ResolvedServerInfoGroup)16 Test (org.junit.Test)13 Attributes (io.grpc.Attributes)12 Status (io.grpc.Status)9 EquivalentAddressGroup (io.grpc.EquivalentAddressGroup)7 InOrder (org.mockito.InOrder)6 Subchannel (io.grpc.LoadBalancer.Subchannel)5 ResolvedServerInfo (io.grpc.ResolvedServerInfo)5 ErrorPicker (io.grpc.grpclb.GrpclbLoadBalancer.ErrorPicker)5 SubchannelPicker (io.grpc.LoadBalancer.SubchannelPicker)4 SocketAddress (java.net.SocketAddress)4 Helper (io.grpc.LoadBalancer.Helper)3 PickSubchannelArgs (io.grpc.LoadBalancer.PickSubchannelArgs)3 ManagedChannel (io.grpc.ManagedChannel)3 Metadata (io.grpc.Metadata)3 MethodDescriptor (io.grpc.MethodDescriptor)3 MockClientTransportInfo (io.grpc.internal.TestUtils.MockClientTransportInfo)3 Matchers.anyString (org.mockito.Matchers.anyString)3 CallOptions (io.grpc.CallOptions)2 ArrayList (java.util.ArrayList)2