Search in sources :

Example 16 with LoadBalancerStateItem

use of com.linkedin.d2.balancer.LoadBalancerStateItem in project rest.li by linkedin.

the class UriLoadBalancerSubscriber method handlePut.

@Override
protected void handlePut(final String cluster, final UriProperties uriProperties) {
    // add tracker clients for uris that we aren't already tracking
    if (uriProperties != null) {
        String clusterName = uriProperties.getClusterName();
        Set<String> serviceNames = _simpleLoadBalancerState.getServicesPerCluster().get(clusterName);
        // updates all the services that these uris provide
        if (serviceNames != null) {
            for (String serviceName : serviceNames) {
                Map<URI, TrackerClient> trackerClients = _simpleLoadBalancerState.getTrackerClients().get(serviceName);
                if (trackerClients == null) {
                    trackerClients = new ConcurrentHashMap<>();
                    _simpleLoadBalancerState.getTrackerClients().put(serviceName, trackerClients);
                }
                for (URI uri : uriProperties.Uris()) {
                    Map<Integer, PartitionData> partitionDataMap = uriProperties.getPartitionDataMap(uri);
                    TrackerClient client = trackerClients.get(uri);
                    Optional<Map<String, Object>> newUriSpecificProperties = Optional.ofNullable(uriProperties.getUriSpecificProperties()).map(uriSpecificProperties -> uriSpecificProperties.get(uri));
                    Optional<Map<String, Object>> oldUriSpecificProperties = Optional.ofNullable(_simpleLoadBalancerState.getUriProperties(clusterName)).map(LoadBalancerStateItem::getProperty).map(UriProperties::getUriSpecificProperties).map(uriSpecificProperties -> uriSpecificProperties.get(uri));
                    if (client == null || !client.getPartitionDataMap().equals(partitionDataMap) || !newUriSpecificProperties.equals(oldUriSpecificProperties)) {
                        client = _simpleLoadBalancerState.buildTrackerClient(uri, uriProperties, serviceName);
                        if (client != null) {
                            debug(_log, "adding new tracker client from updated uri properties: ", client);
                            // notify listeners of the added client
                            for (SimpleLoadBalancerState.SimpleLoadBalancerStateListener listener : _simpleLoadBalancerState.getListeners()) {
                                listener.onClientAdded(serviceName, client);
                            }
                            trackerClients.put(uri, client);
                        }
                    }
                }
            }
        }
    }
    // replace the URI properties
    _simpleLoadBalancerState.getUriProperties().put(cluster, new LoadBalancerStateItem<>(uriProperties, _simpleLoadBalancerState.getVersionAccess().incrementAndGet(), System.currentTimeMillis()));
    // now remove URIs that we're tracking, but have been removed from the new uri properties
    if (uriProperties != null) {
        Set<String> serviceNames = _simpleLoadBalancerState.getServicesPerCluster().get(uriProperties.getClusterName());
        if (serviceNames != null) {
            for (String serviceName : serviceNames) {
                Map<URI, TrackerClient> trackerClients = _simpleLoadBalancerState.getTrackerClients().get(serviceName);
                if (trackerClients != null) {
                    for (Iterator<URI> it = trackerClients.keySet().iterator(); it.hasNext(); ) {
                        URI uri = it.next();
                        if (!uriProperties.Uris().contains(uri)) {
                            TrackerClient client = trackerClients.remove(uri);
                            debug(_log, "removing dead tracker client: ", client);
                            for (SimpleLoadBalancerState.SimpleLoadBalancerStateListener listener : _simpleLoadBalancerState.getListeners()) {
                                listener.onClientRemoved(serviceName, client);
                            }
                        }
                    }
                }
            }
        }
    } else {
        // uri properties was null, we'll just log the event and continues.
        // The reasoning is we might receive a null event when there's a problem writing/reading
        // cache file, or we just started listening to a cluster without any uris yet.
        warn(_log, "received a null uri properties for cluster: ", cluster);
    }
}
Also used : URI(java.net.URI) TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) PartitionData(com.linkedin.d2.balancer.properties.PartitionData) LoadBalancerStateItem(com.linkedin.d2.balancer.LoadBalancerStateItem) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Map(java.util.Map)

Example 17 with LoadBalancerStateItem

use of com.linkedin.d2.balancer.LoadBalancerStateItem in project rest.li by linkedin.

the class ServiceLoadBalancerSubscriber method handlePut.

@Override
protected void handlePut(final String listenTo, final ServiceProperties discoveryProperties) {
    // TODO: pick stable or canary configs if canary exists
    LoadBalancerStateItem<ServiceProperties> oldServicePropertiesItem = _simpleLoadBalancerState.getServiceProperties().get(listenTo);
    _simpleLoadBalancerState.getServiceProperties().put(listenTo, new LoadBalancerStateItem<>(discoveryProperties, _simpleLoadBalancerState.getVersionAccess().incrementAndGet(), System.currentTimeMillis()));
    // always refresh strategies when we receive service event
    if (discoveryProperties != null) {
        // this service is no longer hosted in the old cluster.
        if (oldServicePropertiesItem != null) {
            ServiceProperties oldServiceProperties = oldServicePropertiesItem.getProperty();
            if (oldServiceProperties != null && oldServiceProperties.getClusterName() != null && !oldServiceProperties.getClusterName().equals(discoveryProperties.getClusterName())) {
                Set<String> serviceNames = _simpleLoadBalancerState.getServicesPerCluster().get(oldServiceProperties.getClusterName());
                if (serviceNames != null) {
                    serviceNames.remove(oldServiceProperties.getServiceName());
                }
            }
        }
        _simpleLoadBalancerState.refreshServiceStrategies(discoveryProperties);
        _simpleLoadBalancerState.refreshClients(discoveryProperties);
        // refresh state for which services are on which clusters
        Set<String> serviceNames = _simpleLoadBalancerState.getServicesPerCluster().get(discoveryProperties.getClusterName());
        if (serviceNames == null) {
            serviceNames = Collections.newSetFromMap(new ConcurrentHashMap<>());
            _simpleLoadBalancerState.getServicesPerCluster().put(discoveryProperties.getClusterName(), serviceNames);
        }
        serviceNames.add(discoveryProperties.getServiceName());
    } else if (oldServicePropertiesItem != null) {
        // if we've replaced a service properties with null, update the cluster ->
        // service state that the service is no longer on its cluster.
        ServiceProperties oldServiceProperties = oldServicePropertiesItem.getProperty();
        if (oldServiceProperties != null) {
            Set<String> serviceNames = _simpleLoadBalancerState.getServicesPerCluster().get(oldServiceProperties.getClusterName());
            if (serviceNames != null) {
                serviceNames.remove(oldServiceProperties.getServiceName());
            }
        }
    }
    if (discoveryProperties == null) {
        // we'll just ignore the event and move on.
        // we could receive a null if the file store properties cannot read/write a file.
        // in this case it's better to leave the state intact and not do anything
        _log.warn("We receive a null service properties for {}. ", listenTo);
    }
}
Also used : ServiceProperties(com.linkedin.d2.balancer.properties.ServiceProperties) Set(java.util.Set) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Aggregations

URI (java.net.URI)11 UriProperties (com.linkedin.d2.balancer.properties.UriProperties)10 ServiceProperties (com.linkedin.d2.balancer.properties.ServiceProperties)9 TrackerClient (com.linkedin.d2.balancer.clients.TrackerClient)7 ClusterProperties (com.linkedin.d2.balancer.properties.ClusterProperties)7 HashMap (java.util.HashMap)6 LoadBalancerState (com.linkedin.d2.balancer.LoadBalancerState)5 ServiceUnavailableException (com.linkedin.d2.balancer.ServiceUnavailableException)5 PartitionAccessor (com.linkedin.d2.balancer.util.partitions.PartitionAccessor)5 TransportClient (com.linkedin.r2.transport.common.bridge.client.TransportClient)5 Map (java.util.Map)5 Set (java.util.Set)5 PartitionData (com.linkedin.d2.balancer.properties.PartitionData)4 ArrayList (java.util.ArrayList)4 HashSet (java.util.HashSet)4 LoadBalancerStateItem (com.linkedin.d2.balancer.LoadBalancerStateItem)3 Ring (com.linkedin.d2.balancer.util.hashing.Ring)3 PartitionAccessException (com.linkedin.d2.balancer.util.partitions.PartitionAccessException)3 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)3 FutureCallback (com.linkedin.common.callback.FutureCallback)2