Search in sources :

Example 6 with ConnectivityStateInfo

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

the class LeastRequestLoadBalancerTest method pickAfterStateChange.

@Test
public void pickAfterStateChange() throws Exception {
    InOrder inOrder = inOrder(mockHelper);
    loadBalancer.handleResolvedAddresses(ResolvedAddresses.newBuilder().setAddresses(servers).setAttributes(Attributes.EMPTY).build());
    Subchannel subchannel = loadBalancer.getSubchannels().iterator().next();
    Ref<ConnectivityStateInfo> subchannelStateInfo = subchannel.getAttributes().get(STATE_INFO);
    inOrder.verify(mockHelper).updateBalancingState(eq(CONNECTING), isA(EmptyPicker.class));
    assertThat(subchannelStateInfo.value).isEqualTo(ConnectivityStateInfo.forNonError(IDLE));
    deliverSubchannelState(subchannel, ConnectivityStateInfo.forNonError(READY));
    inOrder.verify(mockHelper).updateBalancingState(eq(READY), pickerCaptor.capture());
    assertThat(pickerCaptor.getValue()).isInstanceOf(ReadyPicker.class);
    assertThat(subchannelStateInfo.value).isEqualTo(ConnectivityStateInfo.forNonError(READY));
    Status error = Status.UNKNOWN.withDescription("¯\\_(ツ)_//¯");
    deliverSubchannelState(subchannel, ConnectivityStateInfo.forTransientFailure(error));
    assertThat(subchannelStateInfo.value.getState()).isEqualTo(TRANSIENT_FAILURE);
    assertThat(subchannelStateInfo.value.getStatus()).isEqualTo(error);
    inOrder.verify(mockHelper).refreshNameResolution();
    inOrder.verify(mockHelper).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
    assertThat(pickerCaptor.getValue()).isInstanceOf(EmptyPicker.class);
    deliverSubchannelState(subchannel, ConnectivityStateInfo.forNonError(IDLE));
    inOrder.verify(mockHelper).refreshNameResolution();
    assertThat(subchannelStateInfo.value.getState()).isEqualTo(TRANSIENT_FAILURE);
    assertThat(subchannelStateInfo.value.getStatus()).isEqualTo(error);
    verify(subchannel, times(2)).requestConnection();
    verify(mockHelper, times(3)).createSubchannel(any(CreateSubchannelArgs.class));
    verifyNoMoreInteractions(mockHelper);
}
Also used : Status(io.grpc.Status) InOrder(org.mockito.InOrder) ConnectivityStateInfo(io.grpc.ConnectivityStateInfo) EmptyPicker(io.grpc.xds.LeastRequestLoadBalancer.EmptyPicker) CreateSubchannelArgs(io.grpc.LoadBalancer.CreateSubchannelArgs) Subchannel(io.grpc.LoadBalancer.Subchannel) Test(org.junit.Test)

Example 7 with ConnectivityStateInfo

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

the class CachedSubchannelPool method takeOrCreateSubchannel.

@Override
public Subchannel takeOrCreateSubchannel(EquivalentAddressGroup eag, Attributes defaultAttributes) {
    final CacheEntry entry = cache.remove(eag);
    final Subchannel subchannel;
    if (entry == null) {
        subchannel = helper.createSubchannel(CreateSubchannelArgs.newBuilder().setAddresses(eag).setAttributes(defaultAttributes).build());
        subchannel.start(new SubchannelStateListener() {

            @Override
            public void onSubchannelState(ConnectivityStateInfo newState) {
                updateCachedSubchannelState(subchannel, newState);
                listener.onSubchannelState(subchannel, newState);
            }
        });
    } else {
        subchannel = entry.subchannel;
        entry.shutdownTimer.cancel();
        // Make the balancer up-to-date with the latest state in case it has changed while it's
        // in the cache.
        helper.getSynchronizationContext().execute(new Runnable() {

            @Override
            public void run() {
                listener.onSubchannelState(subchannel, entry.state);
            }
        });
    }
    return subchannel;
}
Also used : SubchannelStateListener(io.grpc.LoadBalancer.SubchannelStateListener) ConnectivityStateInfo(io.grpc.ConnectivityStateInfo) Subchannel(io.grpc.LoadBalancer.Subchannel)

Example 8 with ConnectivityStateInfo

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

the class GrpclbState method updateServerList.

/**
 * Populate backend servers to be used based on the given list of addresses.
 */
private void updateServerList(List<DropEntry> newDropList, List<BackendAddressGroup> newBackendAddrList, @Nullable GrpclbClientLoadRecorder loadRecorder) {
    HashMap<List<EquivalentAddressGroup>, Subchannel> newSubchannelMap = new HashMap<>();
    List<BackendEntry> newBackendList = new ArrayList<>();
    switch(config.getMode()) {
        case ROUND_ROBIN:
            for (BackendAddressGroup backendAddr : newBackendAddrList) {
                EquivalentAddressGroup eag = backendAddr.getAddresses();
                List<EquivalentAddressGroup> eagAsList = Collections.singletonList(eag);
                Subchannel subchannel = newSubchannelMap.get(eagAsList);
                if (subchannel == null) {
                    subchannel = subchannels.get(eagAsList);
                    if (subchannel == null) {
                        subchannel = subchannelPool.takeOrCreateSubchannel(eag, createSubchannelAttrs());
                        subchannel.requestConnection();
                    }
                    newSubchannelMap.put(eagAsList, subchannel);
                }
                BackendEntry entry;
                // Only picks with tokens are reported to LoadRecorder
                if (backendAddr.getToken() == null) {
                    entry = new BackendEntry(subchannel);
                } else {
                    entry = new BackendEntry(subchannel, loadRecorder, backendAddr.getToken());
                }
                newBackendList.add(entry);
            }
            // Close Subchannels whose addresses have been delisted
            for (Map.Entry<List<EquivalentAddressGroup>, Subchannel> entry : subchannels.entrySet()) {
                List<EquivalentAddressGroup> eagList = entry.getKey();
                if (!newSubchannelMap.containsKey(eagList)) {
                    returnSubchannelToPool(entry.getValue());
                }
            }
            subchannels = Collections.unmodifiableMap(newSubchannelMap);
            break;
        case PICK_FIRST:
            checkState(subchannels.size() <= 1, "Unexpected Subchannel count: %s", subchannels);
            final Subchannel subchannel;
            if (newBackendAddrList.isEmpty()) {
                if (subchannels.size() == 1) {
                    subchannel = subchannels.values().iterator().next();
                    subchannel.shutdown();
                    subchannels = Collections.emptyMap();
                }
                break;
            }
            List<EquivalentAddressGroup> eagList = new ArrayList<>();
            // The PICK_FIRST code path doesn't cache Subchannels.
            for (BackendAddressGroup bag : newBackendAddrList) {
                EquivalentAddressGroup origEag = bag.getAddresses();
                Attributes eagAttrs = origEag.getAttributes();
                if (bag.getToken() != null) {
                    eagAttrs = eagAttrs.toBuilder().set(GrpclbConstants.TOKEN_ATTRIBUTE_KEY, bag.getToken()).build();
                }
                eagList.add(new EquivalentAddressGroup(origEag.getAddresses(), eagAttrs));
            }
            if (subchannels.isEmpty()) {
                subchannel = helper.createSubchannel(CreateSubchannelArgs.newBuilder().setAddresses(eagList).setAttributes(createSubchannelAttrs()).build());
                subchannel.start(new SubchannelStateListener() {

                    @Override
                    public void onSubchannelState(ConnectivityStateInfo newState) {
                        handleSubchannelState(subchannel, newState);
                    }
                });
                if (requestConnectionPending) {
                    subchannel.requestConnection();
                    requestConnectionPending = false;
                }
            } else {
                subchannel = subchannels.values().iterator().next();
                subchannel.updateAddresses(eagList);
            }
            subchannels = Collections.singletonMap(eagList, subchannel);
            newBackendList.add(new BackendEntry(subchannel, new TokenAttachingTracerFactory(loadRecorder)));
            break;
        default:
            throw new AssertionError("Missing case for " + config.getMode());
    }
    dropList = Collections.unmodifiableList(newDropList);
    backendList = Collections.unmodifiableList(newBackendList);
}
Also used : SubchannelStateListener(io.grpc.LoadBalancer.SubchannelStateListener) PooledSubchannelStateListener(io.grpc.grpclb.SubchannelPool.PooledSubchannelStateListener) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Attributes(io.grpc.Attributes) ConnectivityStateInfo(io.grpc.ConnectivityStateInfo) Subchannel(io.grpc.LoadBalancer.Subchannel) EquivalentAddressGroup(io.grpc.EquivalentAddressGroup) ServerList(io.grpc.lb.v1.ServerList) List(java.util.List) ArrayList(java.util.ArrayList) Map(java.util.Map) HashMap(java.util.HashMap)

Example 9 with ConnectivityStateInfo

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

the class HealthCheckingLoadBalancerFactoryTest method serviceConfigChangesServiceNameWhenRpcInactive.

@Test
public void serviceConfigChangesServiceNameWhenRpcInactive() {
    Attributes resolutionAttrs = attrsWithHealthCheckService("TeeService");
    ResolvedAddresses result1 = ResolvedAddresses.newBuilder().setAddresses(resolvedAddressList).setAttributes(resolutionAttrs).build();
    hcLbEventDelivery.handleResolvedAddresses(result1);
    verify(origLb).handleResolvedAddresses(result1);
    verifyNoMoreInteractions(origLb);
    Subchannel subchannel = createSubchannel(0, Attributes.EMPTY);
    SubchannelStateListener mockListener = mockStateListeners[0];
    assertThat(unwrap(subchannel)).isSameInstanceAs(subchannels[0]);
    InOrder inOrder = inOrder(origLb, mockListener);
    HealthImpl healthImpl = healthImpls[0];
    // Underlying subchannel is not READY initially
    ConnectivityStateInfo underlyingErrorState = ConnectivityStateInfo.forTransientFailure(Status.UNAVAILABLE.withDescription("connection refused"));
    deliverSubchannelState(0, underlyingErrorState);
    inOrder.verify(mockListener).onSubchannelState(same(underlyingErrorState));
    inOrder.verifyNoMoreInteractions();
    // Service config returns with the same health check name.
    hcLbEventDelivery.handleResolvedAddresses(result1);
    // It's delivered to origLb, but nothing else happens
    inOrder.verify(origLb).handleResolvedAddresses(result1);
    assertThat(healthImpl.calls).isEmpty();
    verifyNoMoreInteractions(origLb);
    // Service config returns a different health check name.
    resolutionAttrs = attrsWithHealthCheckService("FooService");
    ResolvedAddresses result2 = ResolvedAddresses.newBuilder().setAddresses(resolvedAddressList).setAttributes(resolutionAttrs).build();
    hcLbEventDelivery.handleResolvedAddresses(result2);
    inOrder.verify(origLb).handleResolvedAddresses(result2);
    // Underlying subchannel is now ready
    deliverSubchannelState(0, ConnectivityStateInfo.forNonError(READY));
    // Concluded CONNECTING state
    inOrder.verify(mockListener).onSubchannelState(eq(ConnectivityStateInfo.forNonError(CONNECTING)));
    // Health check RPC is started
    assertThat(healthImpl.calls).hasSize(1);
    // with the new service name
    assertThat(healthImpl.calls.poll().request).isEqualTo(makeRequest("FooService"));
    verifyNoMoreInteractions(origLb, mockListener);
}
Also used : SubchannelStateListener(io.grpc.LoadBalancer.SubchannelStateListener) InOrder(org.mockito.InOrder) ConnectivityStateInfo(io.grpc.ConnectivityStateInfo) Subchannel(io.grpc.LoadBalancer.Subchannel) Attributes(io.grpc.Attributes) ResolvedAddresses(io.grpc.LoadBalancer.ResolvedAddresses) Test(org.junit.Test)

Example 10 with ConnectivityStateInfo

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

the class HealthCheckingLoadBalancerFactoryTest method serviceConfigDisablesHealthCheckWhenRpcInactive.

@Test
public void serviceConfigDisablesHealthCheckWhenRpcInactive() {
    Attributes resolutionAttrs = attrsWithHealthCheckService("TeeService");
    ResolvedAddresses result1 = ResolvedAddresses.newBuilder().setAddresses(resolvedAddressList).setAttributes(resolutionAttrs).build();
    hcLbEventDelivery.handleResolvedAddresses(result1);
    verify(origLb).handleResolvedAddresses(result1);
    verifyNoMoreInteractions(origLb);
    Subchannel subchannel = createSubchannel(0, Attributes.EMPTY);
    assertThat(unwrap(subchannel)).isSameInstanceAs(subchannels[0]);
    InOrder inOrder = inOrder(origLb, mockStateListeners[0]);
    // Underlying subchannel is not READY initially
    ConnectivityStateInfo underlyingErrorState = ConnectivityStateInfo.forTransientFailure(Status.UNAVAILABLE.withDescription("connection refused"));
    deliverSubchannelState(0, underlyingErrorState);
    inOrder.verify(mockStateListeners[0]).onSubchannelState(same(underlyingErrorState));
    inOrder.verifyNoMoreInteractions();
    // NameResolver gives an update without service config, thus health check will be disabled
    ResolvedAddresses result2 = ResolvedAddresses.newBuilder().setAddresses(resolvedAddressList).setAttributes(Attributes.EMPTY).build();
    hcLbEventDelivery.handleResolvedAddresses(result2);
    inOrder.verify(origLb).handleResolvedAddresses(result2);
    // Underlying subchannel is now ready
    deliverSubchannelState(0, ConnectivityStateInfo.forNonError(READY));
    // Since health check is disabled, READY state is propagated directly.
    inOrder.verify(mockStateListeners[0]).onSubchannelState(eq(ConnectivityStateInfo.forNonError(READY)));
    // and there is no health check activity.
    assertThat(healthImpls[0].calls).isEmpty();
    verifyNoMoreInteractions(origLb, mockStateListeners[0]);
}
Also used : InOrder(org.mockito.InOrder) ConnectivityStateInfo(io.grpc.ConnectivityStateInfo) Subchannel(io.grpc.LoadBalancer.Subchannel) Attributes(io.grpc.Attributes) ResolvedAddresses(io.grpc.LoadBalancer.ResolvedAddresses) Test(org.junit.Test)

Aggregations

ConnectivityStateInfo (io.grpc.ConnectivityStateInfo)20 Subchannel (io.grpc.LoadBalancer.Subchannel)14 Test (org.junit.Test)10 Attributes (io.grpc.Attributes)9 Status (io.grpc.Status)9 InOrder (org.mockito.InOrder)7 EquivalentAddressGroup (io.grpc.EquivalentAddressGroup)6 ArrayList (java.util.ArrayList)5 CreateSubchannelArgs (io.grpc.LoadBalancer.CreateSubchannelArgs)4 SubchannelStateListener (io.grpc.LoadBalancer.SubchannelStateListener)4 HashMap (java.util.HashMap)4 Map (java.util.Map)3 ConnectivityState (io.grpc.ConnectivityState)2 ResolvedAddresses (io.grpc.LoadBalancer.ResolvedAddresses)2 EmptyPicker (io.grpc.util.RoundRobinLoadBalancer.EmptyPicker)2 EmptyPicker (io.grpc.xds.LeastRequestLoadBalancer.EmptyPicker)2 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)2 Helper (io.grpc.LoadBalancer.Helper)1 SubchannelPicker (io.grpc.LoadBalancer.SubchannelPicker)1 ManagedChannel (io.grpc.ManagedChannel)1