Search in sources :

Example 1 with SubchannelStateListener

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

the class PickFirstLoadBalancerTest method requestConnectionPicker.

@Test
public void requestConnectionPicker() throws Exception {
    loadBalancer.handleResolvedAddresses(ResolvedAddresses.newBuilder().setAddresses(servers).setAttributes(affinity).build());
    InOrder inOrder = inOrder(mockHelper, mockSubchannel);
    inOrder.verify(mockSubchannel).start(stateListenerCaptor.capture());
    SubchannelStateListener stateListener = stateListenerCaptor.getValue();
    inOrder.verify(mockHelper).updateBalancingState(eq(CONNECTING), any(SubchannelPicker.class));
    inOrder.verify(mockSubchannel).requestConnection();
    stateListener.onSubchannelState(ConnectivityStateInfo.forNonError(IDLE));
    inOrder.verify(mockHelper).updateBalancingState(eq(IDLE), pickerCaptor.capture());
    SubchannelPicker picker = pickerCaptor.getValue();
    // Calling pickSubchannel() twice gave the same result
    assertEquals(picker.pickSubchannel(mockArgs), picker.pickSubchannel(mockArgs));
    // But the picker calls requestConnection() only once
    inOrder.verify(mockSubchannel).requestConnection();
    verify(mockSubchannel, times(2)).requestConnection();
}
Also used : SubchannelPicker(io.grpc.LoadBalancer.SubchannelPicker) InOrder(org.mockito.InOrder) SubchannelStateListener(io.grpc.LoadBalancer.SubchannelStateListener) Test(org.junit.Test)

Example 2 with SubchannelStateListener

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

the class PickFirstLoadBalancerTest method pickAfterStateChangeAfterResolution.

@Test
public void pickAfterStateChangeAfterResolution() throws Exception {
    InOrder inOrder = inOrder(mockHelper);
    loadBalancer.handleResolvedAddresses(ResolvedAddresses.newBuilder().setAddresses(servers).setAttributes(affinity).build());
    inOrder.verify(mockHelper).createSubchannel(createArgsCaptor.capture());
    CreateSubchannelArgs args = createArgsCaptor.getValue();
    assertThat(args.getAddresses()).isEqualTo(servers);
    verify(mockSubchannel).start(stateListenerCaptor.capture());
    SubchannelStateListener stateListener = stateListenerCaptor.getValue();
    verify(mockHelper).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
    Subchannel subchannel = pickerCaptor.getValue().pickSubchannel(mockArgs).getSubchannel();
    reset(mockHelper);
    when(mockHelper.getSynchronizationContext()).thenReturn(syncContext);
    Status error = Status.UNAVAILABLE.withDescription("boom!");
    stateListener.onSubchannelState(ConnectivityStateInfo.forTransientFailure(error));
    inOrder.verify(mockHelper).refreshNameResolution();
    inOrder.verify(mockHelper).updateBalancingState(eq(TRANSIENT_FAILURE), pickerCaptor.capture());
    assertEquals(error, pickerCaptor.getValue().pickSubchannel(mockArgs).getStatus());
    stateListener.onSubchannelState(ConnectivityStateInfo.forNonError(IDLE));
    inOrder.verify(mockHelper).refreshNameResolution();
    inOrder.verify(mockHelper).updateBalancingState(eq(IDLE), pickerCaptor.capture());
    assertEquals(Status.OK, pickerCaptor.getValue().pickSubchannel(mockArgs).getStatus());
    stateListener.onSubchannelState(ConnectivityStateInfo.forNonError(READY));
    inOrder.verify(mockHelper).updateBalancingState(eq(READY), pickerCaptor.capture());
    assertEquals(subchannel, pickerCaptor.getValue().pickSubchannel(mockArgs).getSubchannel());
    // Don't care
    verify(mockHelper, atLeast(0)).getSynchronizationContext();
    verifyNoMoreInteractions(mockHelper);
}
Also used : Status(io.grpc.Status) InOrder(org.mockito.InOrder) SubchannelStateListener(io.grpc.LoadBalancer.SubchannelStateListener) CreateSubchannelArgs(io.grpc.LoadBalancer.CreateSubchannelArgs) Subchannel(io.grpc.LoadBalancer.Subchannel) Test(org.junit.Test)

Example 3 with SubchannelStateListener

use of io.grpc.LoadBalancer.SubchannelStateListener 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 4 with SubchannelStateListener

use of io.grpc.LoadBalancer.SubchannelStateListener 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 5 with SubchannelStateListener

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

the class HealthCheckingLoadBalancerFactoryTest method serviceConfigChangesServiceNameWhenRpcActive.

@Test
public void serviceConfigChangesServiceNameWhenRpcActive() {
    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);
    deliverSubchannelState(0, ConnectivityStateInfo.forNonError(READY));
    inOrder.verify(mockListener).onSubchannelState(eq(ConnectivityStateInfo.forNonError(CONNECTING)));
    HealthImpl healthImpl = healthImpls[0];
    assertThat(healthImpl.calls).hasSize(1);
    ServerSideCall serverCall = healthImpl.calls.poll();
    assertThat(serverCall.cancelled).isFalse();
    assertThat(serverCall.request).isEqualTo(makeRequest("TeeService"));
    // Health check responded
    serverCall.responseObserver.onNext(makeResponse(ServingStatus.SERVING));
    inOrder.verify(mockListener).onSubchannelState(eq(ConnectivityStateInfo.forNonError(READY)));
    // 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);
    verifyNoMoreInteractions(origLb, mockListener);
    // 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);
    // Current health check RPC cancelled.
    assertThat(serverCall.cancelled).isTrue();
    // A second RPC is started immediately
    assertThat(healthImpl.calls).hasSize(1);
    serverCall = healthImpl.calls.poll();
    // with the new service name
    assertThat(serverCall.request).isEqualTo(makeRequest("FooService"));
    // State stays in READY, instead of switching to CONNECTING.
    verifyNoMoreInteractions(origLb, mockListener);
}
Also used : SubchannelStateListener(io.grpc.LoadBalancer.SubchannelStateListener) InOrder(org.mockito.InOrder) Subchannel(io.grpc.LoadBalancer.Subchannel) Attributes(io.grpc.Attributes) ResolvedAddresses(io.grpc.LoadBalancer.ResolvedAddresses) Test(org.junit.Test)

Aggregations

SubchannelStateListener (io.grpc.LoadBalancer.SubchannelStateListener)22 Test (org.junit.Test)19 Subchannel (io.grpc.LoadBalancer.Subchannel)13 InOrder (org.mockito.InOrder)13 Attributes (io.grpc.Attributes)11 ResolvedAddresses (io.grpc.LoadBalancer.ResolvedAddresses)7 CreateSubchannelArgs (io.grpc.LoadBalancer.CreateSubchannelArgs)6 Status (io.grpc.Status)6 SubchannelPicker (io.grpc.LoadBalancer.SubchannelPicker)5 OrcaLoadReport (com.github.xds.data.orca.v3.OrcaLoadReport)4 ConnectivityStateInfo (io.grpc.ConnectivityStateInfo)4 MockClientTransportInfo (io.grpc.internal.TestUtils.MockClientTransportInfo)4 ForwardingSubchannel (io.grpc.util.ForwardingSubchannel)4 EquivalentAddressGroup (io.grpc.EquivalentAddressGroup)3 Helper (io.grpc.LoadBalancer.Helper)3 ProxiedSocketAddress (io.grpc.ProxiedSocketAddress)3 ClientTransportOptions (io.grpc.internal.ClientTransportFactory.ClientTransportOptions)3 SocketAddress (java.net.SocketAddress)3 ChannelLogger (io.grpc.ChannelLogger)2 ClientTransportFactoryBuilder (io.grpc.internal.ManagedChannelImplBuilder.ClientTransportFactoryBuilder)2