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));
}
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"));
}
Aggregations