Search in sources :

Example 11 with ConnectivityStateInfo

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

the class ManagedChannelImplTest method subchannelConnectionBroken_ResolverRefreshedByLb.

@Test
public void subchannelConnectionBroken_ResolverRefreshedByLb() {
    FakeNameResolverFactory nameResolverFactory = new FakeNameResolverFactory.Builder(expectedUri).setServers(Collections.singletonList(new EquivalentAddressGroup(socketAddress))).build();
    channelBuilder.nameResolverFactory(nameResolverFactory);
    createChannel();
    FakeNameResolverFactory.FakeNameResolver resolver = Iterables.getOnlyElement(nameResolverFactory.resolvers);
    assertThat(resolver.refreshCalled).isEqualTo(0);
    ArgumentCaptor<Helper> helperCaptor = ArgumentCaptor.forClass(Helper.class);
    verify(mockLoadBalancerProvider).newLoadBalancer(helperCaptor.capture());
    helper = helperCaptor.getValue();
    SubchannelStateListener listener = new SubchannelStateListener() {

        @Override
        public void onSubchannelState(ConnectivityStateInfo newState) {
            // TRANSIENT_FAILURE or IDLE
            if (newState.getState() == TRANSIENT_FAILURE || newState.getState() == IDLE) {
                helper.refreshNameResolution();
            }
        }
    };
    Subchannel subchannel = createSubchannelSafely(helper, addressGroup, Attributes.EMPTY, listener);
    InternalSubchannel internalSubchannel = (InternalSubchannel) subchannel.getInternalSubchannel();
    internalSubchannel.obtainActiveTransport();
    MockClientTransportInfo transportInfo = transports.poll();
    // Break subchannel connection and simulate load balancer refreshing name resolution
    transportInfo.listener.transportShutdown(Status.UNAVAILABLE.withDescription("unreachable"));
    assertThat(logs).isEmpty();
    assertThat(resolver.refreshCalled).isEqualTo(1);
}
Also used : Helper(io.grpc.LoadBalancer.Helper) SubchannelStateListener(io.grpc.LoadBalancer.SubchannelStateListener) ConnectivityStateInfo(io.grpc.ConnectivityStateInfo) EquivalentAddressGroup(io.grpc.EquivalentAddressGroup) ForwardingSubchannel(io.grpc.util.ForwardingSubchannel) Subchannel(io.grpc.LoadBalancer.Subchannel) UnsupportedClientTransportFactoryBuilder(io.grpc.internal.ManagedChannelImplBuilder.UnsupportedClientTransportFactoryBuilder) ClientTransportFactoryBuilder(io.grpc.internal.ManagedChannelImplBuilder.ClientTransportFactoryBuilder) MockClientTransportInfo(io.grpc.internal.TestUtils.MockClientTransportInfo) Test(org.junit.Test)

Example 12 with ConnectivityStateInfo

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

the class RingHashLoadBalancer method handleResolvedAddresses.

@Override
public void handleResolvedAddresses(ResolvedAddresses resolvedAddresses) {
    logger.log(XdsLogLevel.DEBUG, "Received resolution result: {0}", resolvedAddresses);
    List<EquivalentAddressGroup> addrList = resolvedAddresses.getAddresses();
    if (addrList.isEmpty()) {
        handleNameResolutionError(Status.UNAVAILABLE.withDescription("Ring hash lb error: EDS " + "resolution was successful, but returned server addresses are empty."));
        return;
    }
    Map<EquivalentAddressGroup, EquivalentAddressGroup> latestAddrs = stripAttrs(addrList);
    Set<EquivalentAddressGroup> removedAddrs = Sets.newHashSet(Sets.difference(subchannels.keySet(), latestAddrs.keySet()));
    RingHashConfig config = (RingHashConfig) resolvedAddresses.getLoadBalancingPolicyConfig();
    Map<EquivalentAddressGroup, Long> serverWeights = new HashMap<>();
    long totalWeight = 0L;
    for (EquivalentAddressGroup eag : addrList) {
        Long weight = eag.getAttributes().get(InternalXdsAttributes.ATTR_SERVER_WEIGHT);
        // each occurrence of the address will be counted a weight value of one.
        if (weight == null) {
            weight = 1L;
        }
        totalWeight += weight;
        EquivalentAddressGroup addrKey = stripAttrs(eag);
        if (serverWeights.containsKey(addrKey)) {
            serverWeights.put(addrKey, serverWeights.get(addrKey) + weight);
        } else {
            serverWeights.put(addrKey, weight);
        }
        Subchannel existingSubchannel = subchannels.get(addrKey);
        if (existingSubchannel != null) {
            existingSubchannel.updateAddresses(Collections.singletonList(eag));
            continue;
        }
        Attributes attr = Attributes.newBuilder().set(STATE_INFO, new Ref<>(ConnectivityStateInfo.forNonError(IDLE))).build();
        final Subchannel subchannel = helper.createSubchannel(CreateSubchannelArgs.newBuilder().setAddresses(eag).setAttributes(attr).build());
        subchannel.start(new SubchannelStateListener() {

            @Override
            public void onSubchannelState(ConnectivityStateInfo newState) {
                processSubchannelState(subchannel, newState);
            }
        });
        subchannels.put(addrKey, subchannel);
    }
    long minWeight = Collections.min(serverWeights.values());
    double normalizedMinWeight = (double) minWeight / totalWeight;
    // Scale up the number of hashes per host such that the least-weighted host gets a whole
    // number of hashes on the the ring. Other hosts might not end up with whole numbers, and
    // that's fine (the ring-building algorithm can handle this). This preserves the original
    // implementation's behavior: when weights aren't provided, all hosts should get an equal
    // number of hashes. In the case where this number exceeds the max_ring_size, it's scaled
    // back down to fit.
    double scale = Math.min(Math.ceil(normalizedMinWeight * config.minRingSize) / normalizedMinWeight, (double) config.maxRingSize);
    ring = buildRing(serverWeights, totalWeight, scale);
    // Shut down subchannels for delisted addresses.
    List<Subchannel> removedSubchannels = new ArrayList<>();
    for (EquivalentAddressGroup addr : removedAddrs) {
        removedSubchannels.add(subchannels.remove(addr));
    }
    // Update the picker before shutting down the subchannels, to reduce the chance of race
    // between picking a subchannel and shutting it down.
    updateBalancingState();
    for (Subchannel subchann : removedSubchannels) {
        shutdownSubchannel(subchann);
    }
}
Also used : HashMap(java.util.HashMap) Attributes(io.grpc.Attributes) ArrayList(java.util.ArrayList) ConnectivityStateInfo(io.grpc.ConnectivityStateInfo) EquivalentAddressGroup(io.grpc.EquivalentAddressGroup)

Example 13 with ConnectivityStateInfo

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

the class LeastRequestLoadBalancer method updateBalancingState.

/**
 * Updates picker with the list of active subchannels (state == READY).
 */
@SuppressWarnings("ReferenceEquality")
private void updateBalancingState() {
    List<Subchannel> activeList = filterNonFailingSubchannels(getSubchannels());
    if (activeList.isEmpty()) {
        // No READY subchannels, determine aggregate state and error status
        boolean isConnecting = false;
        Status aggStatus = EMPTY_OK;
        for (Subchannel subchannel : getSubchannels()) {
            ConnectivityStateInfo stateInfo = getSubchannelStateInfoRef(subchannel).value;
            // LRLB will request connection immediately on subchannel IDLE.
            if (stateInfo.getState() == CONNECTING || stateInfo.getState() == IDLE) {
                isConnecting = true;
            }
            if (aggStatus == EMPTY_OK || !aggStatus.isOk()) {
                aggStatus = stateInfo.getStatus();
            }
        }
        updateBalancingState(isConnecting ? CONNECTING : TRANSIENT_FAILURE, // an arbitrary subchannel, otherwise return OK.
        new EmptyPicker(aggStatus));
    } else {
        updateBalancingState(READY, new ReadyPicker(activeList, choiceCount, random));
    }
}
Also used : Status(io.grpc.Status) ConnectivityStateInfo(io.grpc.ConnectivityStateInfo)

Example 14 with ConnectivityStateInfo

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

the class GrpclbLoadBalancer method makePicker.

/**
   * Make a picker out of the current roundRobinList and the states of subchannels.
   */
private SubchannelPicker makePicker() {
    List<RoundRobinEntry> resultList = new ArrayList<RoundRobinEntry>();
    Status error = null;
    for (RoundRobinEntry entry : roundRobinList) {
        Subchannel subchannel = entry.result.getSubchannel();
        if (subchannel != null) {
            Attributes attrs = subchannel.getAttributes();
            ConnectivityStateInfo stateInfo = attrs.get(STATE_INFO).get();
            if (stateInfo.getState() == READY) {
                resultList.add(entry);
            } else if (stateInfo.getState() == TRANSIENT_FAILURE) {
                error = stateInfo.getStatus();
            }
        } else {
            // This is a drop entry.
            resultList.add(entry);
        }
    }
    if (resultList.isEmpty()) {
        if (error != null) {
            logger.log(Level.FINE, "[{0}] No ready Subchannel. Using error: {1}", new Object[] { logId, error });
            return new ErrorPicker(error);
        } else {
            logger.log(Level.FINE, "[{0}] No ready Subchannel and no error", logId);
            return BUFFER_PICKER;
        }
    } else {
        logger.log(Level.FINE, "[{0}] Using list {1}", new Object[] { logId, resultList });
        return new RoundRobinPicker(resultList);
    }
}
Also used : Status(io.grpc.Status) ConnectivityStateInfo(io.grpc.ConnectivityStateInfo) ArrayList(java.util.ArrayList) Attributes(io.grpc.Attributes)

Example 15 with ConnectivityStateInfo

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

the class LeastRequestLoadBalancer method handleResolvedAddresses.

@Override
public void handleResolvedAddresses(ResolvedAddresses resolvedAddresses) {
    LeastRequestConfig config = (LeastRequestConfig) resolvedAddresses.getLoadBalancingPolicyConfig();
    // Config may be null if least_request is used outside xDS
    if (config != null) {
        choiceCount = config.choiceCount;
    }
    List<EquivalentAddressGroup> servers = resolvedAddresses.getAddresses();
    Set<EquivalentAddressGroup> currentAddrs = subchannels.keySet();
    Map<EquivalentAddressGroup, EquivalentAddressGroup> latestAddrs = stripAttrs(servers);
    Set<EquivalentAddressGroup> removedAddrs = setsDifference(currentAddrs, latestAddrs.keySet());
    for (Map.Entry<EquivalentAddressGroup, EquivalentAddressGroup> latestEntry : latestAddrs.entrySet()) {
        EquivalentAddressGroup strippedAddressGroup = latestEntry.getKey();
        EquivalentAddressGroup originalAddressGroup = latestEntry.getValue();
        Subchannel existingSubchannel = subchannels.get(strippedAddressGroup);
        if (existingSubchannel != null) {
            // EAG's Attributes may have changed.
            existingSubchannel.updateAddresses(Collections.singletonList(originalAddressGroup));
            continue;
        }
        // Create new subchannels for new addresses.
        Attributes.Builder subchannelAttrs = Attributes.newBuilder().set(STATE_INFO, new Ref<>(ConnectivityStateInfo.forNonError(IDLE))).set(IN_FLIGHTS, new AtomicInteger(0));
        final Subchannel subchannel = checkNotNull(helper.createSubchannel(CreateSubchannelArgs.newBuilder().setAddresses(originalAddressGroup).setAttributes(subchannelAttrs.build()).build()), "subchannel");
        subchannel.start(new SubchannelStateListener() {

            @Override
            public void onSubchannelState(ConnectivityStateInfo state) {
                processSubchannelState(subchannel, state);
            }
        });
        subchannels.put(strippedAddressGroup, subchannel);
        subchannel.requestConnection();
    }
    ArrayList<Subchannel> removedSubchannels = new ArrayList<>();
    for (EquivalentAddressGroup addressGroup : removedAddrs) {
        removedSubchannels.add(subchannels.remove(addressGroup));
    }
    // Update the picker before shutting down the subchannels, to reduce the chance of the race
    // between picking a subchannel and shutting it down.
    updateBalancingState();
    // Shutdown removed subchannels
    for (Subchannel removedSubchannel : removedSubchannels) {
        shutdownSubchannel(removedSubchannel);
    }
}
Also used : Attributes(io.grpc.Attributes) ArrayList(java.util.ArrayList) ConnectivityStateInfo(io.grpc.ConnectivityStateInfo) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) EquivalentAddressGroup(io.grpc.EquivalentAddressGroup) HashMap(java.util.HashMap) Map(java.util.Map)

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