use of com.linkedin.d2.balancer.clients.TrackerClient in project rest.li by linkedin.
the class SimpleLoadBalancerStateTest method testSchemeNotSupported.
@Test
public void testSchemeNotSupported() {
reset();
// Create https uri and scheme only supports http
URI uri = URI.create("https://cluster-1/test1");
List<String> schemes = new ArrayList<>();
Map<Integer, PartitionData> partitionData = new HashMap<>(1);
partitionData.put(DefaultPartitionAccessor.DEFAULT_PARTITION_ID, new PartitionData(1d));
Map<URI, Map<Integer, PartitionData>> uriData = new HashMap<>();
uriData.put(uri, partitionData);
schemes.add("http");
// set up state
_state.listenToCluster("cluster-1", new NullStateListenerCallback());
_state.listenToService("service-1", new NullStateListenerCallback());
_serviceRegistry.put("service-1", new ServiceProperties("service-1", "cluster-1", "/test", Arrays.asList("random"), Collections.emptyMap(), null, null, schemes, null));
assertNull(_state.getClient("service-1", uri));
_uriRegistry.put("cluster-1", new UriProperties("cluster-1", uriData));
TrackerClient client = _state.getClient("service-1", uri);
assertNull(client);
}
use of com.linkedin.d2.balancer.clients.TrackerClient in project rest.li by linkedin.
the class SimpleLoadBalancerTest method testLoadBalancerDropRate.
/**
* This test simulates dropping requests by playing with OverrideDropRate in config
*/
@Test(groups = { "small", "back-end" })
public void testLoadBalancerDropRate() throws ServiceUnavailableException, ExecutionException, InterruptedException {
final int RETRY = 10;
for (int tryAgain = 0; tryAgain < RETRY; ++tryAgain) {
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("rr", new RandomLoadBalancerStrategyFactory());
loadBalancerStrategyFactories.put("degrader", new DegraderLoadBalancerStrategyFactoryV3());
// PrpcClientFactory();
// new
clientFactories.put(PropertyKeys.HTTP_SCHEME, new DoNothingClientFactory());
// HttpClientFactory();
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();
URI uri1 = URI.create("http://test.qa1.com:1234");
URI uri2 = URI.create("http://test.qa2.com:2345");
URI uri3 = URI.create("http://test.qa3.com:6789");
Map<Integer, PartitionData> partitionData = new HashMap<>(1);
partitionData.put(DEFAULT_PARTITION_ID, new PartitionData(1d));
Map<URI, Map<Integer, PartitionData>> uriData = new HashMap<>(3);
uriData.put(uri1, partitionData);
uriData.put(uri2, partitionData);
uriData.put(uri3, partitionData);
prioritizedSchemes.add(PropertyKeys.HTTP_SCHEME);
clusterRegistry.put("cluster-1", new ClusterProperties("cluster-1"));
serviceRegistry.put("foo", new ServiceProperties("foo", "cluster-1", "/foo", Arrays.asList("degrader"), Collections.<String, Object>emptyMap(), null, null, prioritizedSchemes, null));
uriRegistry.put("cluster-1", new UriProperties("cluster-1", uriData));
URI expectedUri1 = URI.create("http://test.qa1.com:1234/foo");
URI expectedUri2 = URI.create("http://test.qa2.com:2345/foo");
URI expectedUri3 = URI.create("http://test.qa3.com:6789/foo");
Set<URI> expectedUris = new HashSet<>();
expectedUris.add(expectedUri1);
expectedUris.add(expectedUri2);
expectedUris.add(expectedUri3);
Random random = new Random();
for (int i = 0; i < 100; ++i) {
try {
RewriteLoadBalancerClient client = (RewriteLoadBalancerClient) loadBalancer.getClient(new URIRequest("d2://foo/52"), new RequestContext());
assertTrue(client.getDecoratedClient() instanceof RewriteClient);
RewriteClient rewriteClient = (RewriteClient) client.getDecoratedClient();
assertTrue(rewriteClient.getDecoratedClient() instanceof TrackerClient);
DegraderTrackerClient tClient = (DegraderTrackerClient) rewriteClient.getDecoratedClient();
DegraderImpl degrader = (DegraderImpl) tClient.getDegrader(DEFAULT_PARTITION_ID);
DegraderImpl.Config cfg = new DegraderImpl.Config(degrader.getConfig());
// Change DropRate to 0.0 at the rate of 1/3
cfg.setOverrideDropRate((random.nextInt(2) == 0) ? 1.0 : 0.0);
degrader.setConfig(cfg);
assertTrue(expectedUris.contains(client.getUri()));
assertEquals(client.getUri().getScheme(), PropertyKeys.HTTP_SCHEME);
} catch (ServiceUnavailableException e) {
assertTrue(e.toString().contains("in a bad state (high latency/high error)"));
}
}
final CountDownLatch latch = new CountDownLatch(1);
PropertyEventShutdownCallback callback = new PropertyEventShutdownCallback() {
@Override
public void done() {
latch.countDown();
}
};
state.shutdown(callback);
if (!latch.await(60, TimeUnit.SECONDS)) {
fail("unable to shutdown state");
}
executorService.shutdownNow();
assertTrue(executorService.isShutdown(), "ExecutorService should have shut down!");
}
}
use of com.linkedin.d2.balancer.clients.TrackerClient in project rest.li by linkedin.
the class StateUpdaterTest method testInitializePartitionWithDoNotLoadBalance.
@Test(dataProvider = "trueFalse")
public void testInitializePartitionWithDoNotLoadBalance(boolean doNotLoadBalance) {
double initialHealthScore = 0.01;
D2RelativeStrategyProperties relativeStrategyProperties = new D2RelativeStrategyProperties().setInitialHealthScore(initialHealthScore);
setup(relativeStrategyProperties, new ConcurrentHashMap<>());
List<TrackerClient> trackerClients = TrackerClientMockHelper.mockTrackerClients(2, Arrays.asList(20, 20), Arrays.asList(10, 10), Arrays.asList(200L, 500L), Arrays.asList(100L, 200L), Arrays.asList(0, 0), false, Arrays.asList(false, doNotLoadBalance));
assertTrue(_stateUpdater.getPointsMap(DEFAULT_PARTITION_ID).isEmpty(), "There should be no state before initialization");
_stateUpdater.updateState(new HashSet<>(trackerClients), DEFAULT_PARTITION_ID, DEFAULT_CLUSTER_GENERATION_ID, false);
final TrackerClient trackerClient0 = trackerClients.get(0);
final TrackerClient trackerClient1 = trackerClients.get(1);
assertTrackerClientState(DEFAULT_PARTITION_ID, trackerClient0, (int) (initialHealthScore * RelativeLoadBalancerStrategyFactory.DEFAULT_POINTS_PER_WEIGHT), false);
if (!doNotLoadBalance) {
assertTrackerClientState(DEFAULT_PARTITION_ID, trackerClient1, (int) (initialHealthScore * RelativeLoadBalancerStrategyFactory.DEFAULT_POINTS_PER_WEIGHT), false);
} else {
assertTrackerClientState(DEFAULT_PARTITION_ID, trackerClient1, HEALTHY_POINTS, false);
}
}
use of com.linkedin.d2.balancer.clients.TrackerClient in project rest.li by linkedin.
the class StateUpdaterTest method testInitializePartitionWithMultipleThreads.
@Test
public void testInitializePartitionWithMultipleThreads() throws InterruptedException {
setup(new D2RelativeStrategyProperties(), new ConcurrentHashMap<>());
List<TrackerClient> trackerClients = TrackerClientMockHelper.mockTrackerClients(2, Arrays.asList(20, 20), Arrays.asList(10, 10), Arrays.asList(200L, 500L), Arrays.asList(100L, 200L), Arrays.asList(0, 0));
assertTrue(_stateUpdater.getPointsMap(DEFAULT_PARTITION_ID).isEmpty(), "There should be no state before initialization");
int numThreads = 50;
ExecutorService executorService = Executors.newFixedThreadPool(numThreads);
CountDownLatch countDownLatch = new CountDownLatch(numThreads);
Runnable runnable = () -> {
PartitionState lastState = _stateUpdater.getPartitionState(DEFAULT_PARTITION_ID);
_stateUpdater.updateState(new HashSet<>(trackerClients), DEFAULT_PARTITION_ID, DEFAULT_CLUSTER_GENERATION_ID, false);
PartitionState currentState = _stateUpdater.getPartitionState(DEFAULT_PARTITION_ID);
if (lastState != null) {
assertEquals(currentState, lastState, "The partition state should always be the same object created by the first thread that obtained the lock");
}
};
for (int threadIndex = 0; threadIndex < numThreads; threadIndex++) {
runIndividualConcurrentTask(executorService, runnable, countDownLatch);
}
if (!countDownLatch.await(2, TimeUnit.SECONDS)) {
fail("Initialization failed to finish within 2 seconds");
}
assertEquals(_stateUpdater.getPointsMap(DEFAULT_PARTITION_ID).get(trackerClients.get(0).getUri()).intValue(), HEALTHY_POINTS);
assertEquals(_stateUpdater.getPointsMap(DEFAULT_PARTITION_ID).get(trackerClients.get(1).getUri()).intValue(), HEALTHY_POINTS);
executorService.shutdown();
}
use of com.linkedin.d2.balancer.clients.TrackerClient in project rest.li by linkedin.
the class StateUpdaterTest method testUpdateMultiplePartitions.
@Test
public void testUpdateMultiplePartitions() {
/**
* There are 2 partitions, and 4 tracker clients in total.
* Partition 0 contains tracker client 1,2,3
* Partition 1 contains tracker client 3,4
* TrackerClient 3 will be unhealthy in partition 0, but not in partition 1
*/
List<TrackerClient> trackerClients1 = TrackerClientMockHelper.mockTrackerClients(3, Arrays.asList(20, 20, 20), Arrays.asList(10, 10, 10), Arrays.asList(200L, 300L, 1000L), Arrays.asList(100L, 200L, 500L), Arrays.asList(0, 0, 0));
List<TrackerClient> trackerClients2 = TrackerClientMockHelper.mockTrackerClients(1, Arrays.asList(20), Arrays.asList(10), Arrays.asList(1000L), Arrays.asList(600L), Arrays.asList(0));
trackerClients2.add(trackerClients1.get(2));
PartitionState state1 = new PartitionStateTestDataBuilder().setClusterGenerationId(DEFAULT_CLUSTER_GENERATION_ID).setTrackerClientStateMap(trackerClients1, Arrays.asList(StateUpdater.MAX_HEALTH_SCORE, StateUpdater.MAX_HEALTH_SCORE, StateUpdater.MAX_HEALTH_SCORE), Arrays.asList(TrackerClientState.HealthState.HEALTHY, TrackerClientState.HealthState.HEALTHY, TrackerClientState.HealthState.HEALTHY), Arrays.asList(30, 30, 30)).build();
PartitionState state2 = new PartitionStateTestDataBuilder().setClusterGenerationId(DEFAULT_CLUSTER_GENERATION_ID).setTrackerClientStateMap(trackerClients2, Arrays.asList(StateUpdater.MAX_HEALTH_SCORE, StateUpdater.MAX_HEALTH_SCORE), Arrays.asList(TrackerClientState.HealthState.HEALTHY, TrackerClientState.HealthState.HEALTHY), Arrays.asList(30, 30)).build();
ConcurrentMap<Integer, PartitionState> partitionLoadBalancerStateMap = new ConcurrentHashMap<>();
partitionLoadBalancerStateMap.put(0, state1);
partitionLoadBalancerStateMap.put(1, state2);
setup(new D2RelativeStrategyProperties(), partitionLoadBalancerStateMap);
_stateUpdater.updateState();
URI overlapUri = trackerClients1.get(2).getUri();
assertEquals(partitionLoadBalancerStateMap.get(0).getPointsMap().get(overlapUri).intValue(), (int) (HEALTHY_POINTS - RelativeLoadBalancerStrategyFactory.DEFAULT_DOWN_STEP * RelativeLoadBalancerStrategyFactory.DEFAULT_POINTS_PER_WEIGHT));
assertEquals(partitionLoadBalancerStateMap.get(1).getPointsMap().get(overlapUri).intValue(), HEALTHY_POINTS);
}
Aggregations