Search in sources :

Example 1 with HostOverrideList

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

the class SimpleLoadBalancer method getClient.

/**
 * Given a Request, returns a TransportClient that can handle requests for the Request.
 * The callback is given a client that can be called to retrieve data for the URN.
 *
 * @param request
 *          A request whose URI is a URL of the format "d2://>servicename</optional/path".
 * @param requestContext context for this request
 * @throws ServiceUnavailableException
 *           If the load balancer can't figure out how to reach a service for the given
 *           URN, an ServiceUnavailableException will be thrown.
 */
@Override
public void getClient(Request request, RequestContext requestContext, Callback<TransportClient> clientCallback) {
    URI uri = request.getURI();
    debug(_log, "get client for uri: ", uri);
    if (!D2_SCHEME_NAME.equalsIgnoreCase(uri.getScheme())) {
        throw new IllegalArgumentException("Unsupported scheme in URI " + uri);
    }
    // get the service for this uri
    String extractedServiceName = LoadBalancerUtil.getServiceNameFromUri(uri);
    listenToServiceAndCluster(extractedServiceName, Callbacks.handle(service -> {
        String serviceName = service.getServiceName();
        String clusterName = service.getClusterName();
        try {
            ClusterProperties cluster = getClusterProperties(serviceName, clusterName);
            // Check if we want to override the service URL and bypass choosing among the existing
            // tracker clients. This is useful when the service we want is not announcing itself to
            // the cluster, ie a private service for a set of clients. This mechanism is deprecated;
            // use host override list instead.
            @SuppressWarnings("deprecation") URI targetService = LoadBalancerUtil.TargetHints.getRequestContextTargetService(requestContext);
            // Checks if we have a host override list provided in the request context. If present,
            // get the override URI available override for the current cluster and service names.
            HostOverrideList overrides = (HostOverrideList) requestContext.getLocalAttr(HOST_OVERRIDE_LIST);
            URI override = overrides == null ? null : overrides.getOverride(clusterName, serviceName);
            if (targetService == null && override == null) {
                LoadBalancerStateItem<UriProperties> uriItem = getUriItem(serviceName, clusterName, cluster);
                UriProperties uris = uriItem.getProperty();
                List<LoadBalancerState.SchemeStrategyPair> orderedStrategies = _state.getStrategiesForService(serviceName, service.getPrioritizedSchemes());
                TrackerClient trackerClient = chooseTrackerClient(request, requestContext, serviceName, clusterName, cluster, uriItem, uris, orderedStrategies, service);
                String clusterAndServiceUriString = trackerClient.getUri() + service.getPath();
                _serviceAvailableStats.inc();
                clientCallback.onSuccess(new RewriteLoadBalancerClient(serviceName, URI.create(clusterAndServiceUriString), trackerClient));
            } else {
                URI target = override == null ? targetService : URI.create(override + service.getPath());
                if (targetService != null && override != null) {
                    _log.warn("Both TargetHints and HostOverrideList are found. HostOverList will take precedence %s.", target);
                }
                if (_log.isDebugEnabled()) {
                    _log.debug("Rewrite URI as specified in the TargetHints/HostOverrideList {} for cluster {} and service {}.", target, clusterName, serviceName);
                }
                TransportClient transportClient = _state.getClient(serviceName, target.getScheme());
                if (transportClient == null) {
                    throw new ServiceUnavailableException(serviceName, String.format("PEGA_1001. Cannot find transportClient for service %s and scheme %s with URI specified in" + "TargetHints/HostOverrideList %s", serviceName, target.getScheme(), target));
                }
                clientCallback.onSuccess(new RewriteLoadBalancerClient(serviceName, target, transportClient));
            }
        } catch (ServiceUnavailableException e) {
            clientCallback.onError(e);
        }
    }, clientCallback));
}
Also used : LoadBalancerStateListenerCallback(com.linkedin.d2.balancer.LoadBalancerState.LoadBalancerStateListenerCallback) NullStateListenerCallback(com.linkedin.d2.balancer.LoadBalancerState.NullStateListenerCallback) LoadBalancerStrategy(com.linkedin.d2.balancer.strategies.LoadBalancerStrategy) LoggerFactory(org.slf4j.LoggerFactory) TimeoutException(java.util.concurrent.TimeoutException) Random(java.util.Random) KeysAndHosts(com.linkedin.d2.balancer.util.KeysAndHosts) Request(com.linkedin.r2.message.Request) LoadBalancerStateItem(com.linkedin.d2.balancer.LoadBalancerStateItem) TransportClientFactory(com.linkedin.r2.transport.common.TransportClientFactory) Map(java.util.Map) URI(java.net.URI) HashFunction(com.linkedin.d2.balancer.util.hashing.HashFunction) ClusterProperties(com.linkedin.d2.balancer.properties.ClusterProperties) Collection(java.util.Collection) LogUtil.warn(com.linkedin.d2.discovery.util.LogUtil.warn) UriProperties(com.linkedin.d2.balancer.properties.UriProperties) Set(java.util.Set) Collectors(java.util.stream.Collectors) TimeoutCallback(com.linkedin.r2.transport.http.client.TimeoutCallback) RewriteLoadBalancerClient(com.linkedin.d2.balancer.clients.RewriteLoadBalancerClient) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) None(com.linkedin.common.util.None) LoadBalancer(com.linkedin.d2.balancer.LoadBalancer) LoadBalancerState(com.linkedin.d2.balancer.LoadBalancerState) PropertyEventShutdownCallback(com.linkedin.d2.discovery.event.PropertyEventThread.PropertyEventShutdownCallback) PartitionData(com.linkedin.d2.balancer.properties.PartitionData) ServiceProperties(com.linkedin.d2.balancer.properties.ServiceProperties) PartitionInfoProvider(com.linkedin.d2.balancer.util.partitions.PartitionInfoProvider) Callbacks(com.linkedin.common.callback.Callbacks) DarkClusterConfigMap(com.linkedin.d2.DarkClusterConfigMap) PartitionAccessException(com.linkedin.d2.balancer.util.partitions.PartitionAccessException) LogUtil.debug(com.linkedin.d2.discovery.util.LogUtil.debug) FutureCallback(com.linkedin.common.callback.FutureCallback) PartitionAccessor(com.linkedin.d2.balancer.util.partitions.PartitionAccessor) Callback(com.linkedin.common.callback.Callback) TransportClient(com.linkedin.r2.transport.common.bridge.client.TransportClient) HashMap(java.util.HashMap) LoadBalancerClusterListener(com.linkedin.d2.balancer.LoadBalancerClusterListener) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) HashRingProvider(com.linkedin.d2.balancer.util.hashing.HashRingProvider) ClusterInfoProvider(com.linkedin.d2.balancer.util.ClusterInfoProvider) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) Ring(com.linkedin.d2.balancer.util.hashing.Ring) HostOverrideList(com.linkedin.d2.balancer.util.HostOverrideList) ClientFactoryProvider(com.linkedin.d2.balancer.util.ClientFactoryProvider) SubsettingState(com.linkedin.d2.balancer.subsetting.SubsettingState) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) Stats(com.linkedin.d2.discovery.util.Stats) HostToKeyMapper(com.linkedin.d2.balancer.util.HostToKeyMapper) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) WarmUpService(com.linkedin.d2.balancer.WarmUpService) RequestContext(com.linkedin.r2.message.RequestContext) TreeMap(java.util.TreeMap) LogUtil.info(com.linkedin.d2.discovery.util.LogUtil.info) KeyMapper(com.linkedin.d2.balancer.KeyMapper) MapKeyResult(com.linkedin.d2.balancer.util.MapKeyResult) ServiceUnavailableException(com.linkedin.d2.balancer.ServiceUnavailableException) Collections(java.util.Collections) TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) LoadBalancerUtil(com.linkedin.d2.balancer.util.LoadBalancerUtil) TransportClient(com.linkedin.r2.transport.common.bridge.client.TransportClient) RewriteLoadBalancerClient(com.linkedin.d2.balancer.clients.RewriteLoadBalancerClient) ServiceUnavailableException(com.linkedin.d2.balancer.ServiceUnavailableException) URI(java.net.URI) LoadBalancerState(com.linkedin.d2.balancer.LoadBalancerState) TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) UriProperties(com.linkedin.d2.balancer.properties.UriProperties) HostOverrideList(com.linkedin.d2.balancer.util.HostOverrideList) ClusterProperties(com.linkedin.d2.balancer.properties.ClusterProperties) LoadBalancerStateItem(com.linkedin.d2.balancer.LoadBalancerStateItem) List(java.util.List) ArrayList(java.util.ArrayList) HostOverrideList(com.linkedin.d2.balancer.util.HostOverrideList)

Example 2 with HostOverrideList

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

the class SimpleLoadBalancerTest method testGetClientHostOverrideList.

/**
 * Tests getClient() when with host override list specified in the request context.
 * @throws Exception
 */
@Test
public void testGetClientHostOverrideList() throws Exception {
    Map<String, LoadBalancerStrategyFactory<? extends LoadBalancerStrategy>> loadBalancerStrategyFactories = new HashMap<>();
    Map<String, TransportClientFactory> clientFactories = new HashMap<>();
    List<String> prioritizedSchemes = new ArrayList<>();
    MockStore<ServiceProperties> serviceRegistry = new MockStore<>();
    MockStore<ClusterProperties> clusterRegistry = new MockStore<>();
    MockStore<UriProperties> uriRegistry = new MockStore<>();
    ScheduledExecutorService executorService = new SynchronousExecutorService();
    loadBalancerStrategyFactories.put("degrader", new DegraderLoadBalancerStrategyFactoryV3());
    clientFactories.put(PropertyKeys.HTTP_SCHEME, new DoNothingClientFactory());
    SimpleLoadBalancerState state = new SimpleLoadBalancerState(executorService, uriRegistry, clusterRegistry, serviceRegistry, clientFactories, loadBalancerStrategyFactories);
    SimpleLoadBalancer loadBalancer = new SimpleLoadBalancer(state, 5, TimeUnit.SECONDS, _d2Executor);
    FutureCallback<None> balancerCallback = new FutureCallback<>();
    loadBalancer.start(balancerCallback);
    balancerCallback.get();
    Map<Integer, PartitionData> partitionData = new HashMap<>(1);
    partitionData.put(DEFAULT_PARTITION_ID, new PartitionData(1d));
    Map<URI, Map<Integer, PartitionData>> uriData = new HashMap<>(2);
    uriData.put(URI.create("http://host1/path"), partitionData);
    prioritizedSchemes.add(PropertyKeys.HTTP_SCHEME);
    String cluster1 = "Cluster1";
    String cluster2 = "Cluster2";
    String service1 = "service1";
    clusterRegistry.put(cluster1, new ClusterProperties(cluster1, Collections.emptyList(), Collections.emptyMap(), new HashSet<>(), NullPartitionProperties.getInstance()));
    serviceRegistry.put(service1, new ServiceProperties(service1, cluster1, "/service1Path", Arrays.asList("degrader"), Collections.<String, Object>emptyMap(), null, null, prioritizedSchemes, null));
    uriRegistry.put(cluster1, new UriProperties(cluster1, uriData));
    URI override = URI.create("http://override/path");
    URI expected = URI.create("http://override/path/service1Path");
    URIRequest uriRequest = new URIRequest("d2://service1");
    HostOverrideList clusterOverrides = new HostOverrideList();
    clusterOverrides.addClusterOverride(cluster1, override);
    RequestContext clusterContext = new RequestContext();
    clusterContext.putLocalAttr(HOST_OVERRIDE_LIST, clusterOverrides);
    Assert.assertEquals(((RewriteLoadBalancerClient) loadBalancer.getClient(uriRequest, clusterContext)).getUri(), URI.create("http://override/path/service1Path"));
    HostOverrideList serviceOverrides = new HostOverrideList();
    serviceOverrides.addServiceOverride(service1, override);
    RequestContext serviceContext = new RequestContext();
    serviceContext.putLocalAttr(HOST_OVERRIDE_LIST, serviceOverrides);
    Assert.assertEquals(((RewriteLoadBalancerClient) loadBalancer.getClient(uriRequest, serviceContext)).getUri(), URI.create("http://override/path/service1Path"));
    HostOverrideList overrides = new HostOverrideList();
    overrides.addOverride(override);
    RequestContext context = new RequestContext();
    context.putLocalAttr(HOST_OVERRIDE_LIST, overrides);
    Assert.assertEquals(((RewriteLoadBalancerClient) loadBalancer.getClient(uriRequest, context)).getUri(), URI.create("http://override/path/service1Path"));
    HostOverrideList unrelatedClusterOverrides = new HostOverrideList();
    unrelatedClusterOverrides.addClusterOverride(cluster2, override);
    RequestContext unrelatedClusterContext = new RequestContext();
    unrelatedClusterContext.putLocalAttr(HOST_OVERRIDE_LIST, unrelatedClusterOverrides);
    Assert.assertEquals(((RewriteLoadBalancerClient) loadBalancer.getClient(uriRequest, unrelatedClusterContext)).getUri(), URI.create("http://host1/path/service1Path"));
    HostOverrideList unrelatedServiceOverrides = new HostOverrideList();
    unrelatedServiceOverrides.addClusterOverride(cluster2, override);
    RequestContext unrelatedServiceContext = new RequestContext();
    unrelatedServiceContext.putLocalAttr(HOST_OVERRIDE_LIST, unrelatedServiceOverrides);
    Assert.assertEquals(((RewriteLoadBalancerClient) loadBalancer.getClient(uriRequest, unrelatedServiceContext)).getUri(), URI.create("http://host1/path/service1Path"));
}
Also used : HashMap(java.util.HashMap) DegraderLoadBalancerStrategyFactoryV3(com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerStrategyFactoryV3) ArrayList(java.util.ArrayList) MockStore(com.linkedin.d2.discovery.stores.mock.MockStore) URI(java.net.URI) PartitionData(com.linkedin.d2.balancer.properties.PartitionData) UriProperties(com.linkedin.d2.balancer.properties.UriProperties) HostOverrideList(com.linkedin.d2.balancer.util.HostOverrideList) RequestContext(com.linkedin.r2.message.RequestContext) TransportClientFactory(com.linkedin.r2.transport.common.TransportClientFactory) FutureCallback(com.linkedin.common.callback.FutureCallback) HashSet(java.util.HashSet) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) SynchronousExecutorService(com.linkedin.d2.discovery.event.SynchronousExecutorService) RandomLoadBalancerStrategyFactory(com.linkedin.d2.balancer.strategies.random.RandomLoadBalancerStrategyFactory) LoadBalancerStrategyFactory(com.linkedin.d2.balancer.strategies.LoadBalancerStrategyFactory) URIRequest(com.linkedin.d2.balancer.util.URIRequest) LoadBalancerStrategy(com.linkedin.d2.balancer.strategies.LoadBalancerStrategy) ServiceProperties(com.linkedin.d2.balancer.properties.ServiceProperties) ClusterProperties(com.linkedin.d2.balancer.properties.ClusterProperties) None(com.linkedin.common.util.None) Map(java.util.Map) DarkClusterConfigMap(com.linkedin.d2.DarkClusterConfigMap) HashMap(java.util.HashMap) Test(org.testng.annotations.Test)

Aggregations

FutureCallback (com.linkedin.common.callback.FutureCallback)2 None (com.linkedin.common.util.None)2 DarkClusterConfigMap (com.linkedin.d2.DarkClusterConfigMap)2 ClusterProperties (com.linkedin.d2.balancer.properties.ClusterProperties)2 PartitionData (com.linkedin.d2.balancer.properties.PartitionData)2 ServiceProperties (com.linkedin.d2.balancer.properties.ServiceProperties)2 UriProperties (com.linkedin.d2.balancer.properties.UriProperties)2 LoadBalancerStrategy (com.linkedin.d2.balancer.strategies.LoadBalancerStrategy)2 HostOverrideList (com.linkedin.d2.balancer.util.HostOverrideList)2 RequestContext (com.linkedin.r2.message.RequestContext)2 TransportClientFactory (com.linkedin.r2.transport.common.TransportClientFactory)2 URI (java.net.URI)2 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 Map (java.util.Map)2 ScheduledExecutorService (java.util.concurrent.ScheduledExecutorService)2 Callback (com.linkedin.common.callback.Callback)1 Callbacks (com.linkedin.common.callback.Callbacks)1 KeyMapper (com.linkedin.d2.balancer.KeyMapper)1