Search in sources :

Example 26 with DegraderTrackerClient

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

the class DegraderLoadBalancerTest method runMultiThreadedTest.

private void runMultiThreadedTest(final DegraderLoadBalancerStrategyAdapter strategyAdapter, final List<DegraderTrackerClient> clients, final int numberOfThread, final boolean trackerClientMustNotBeNull) {
    final CountDownLatch exitLatch = new CountDownLatch(numberOfThread);
    final CountDownLatch startLatch = new CountDownLatch(numberOfThread);
    ExecutorService executorService = Executors.newFixedThreadPool(numberOfThread);
    List<Future<Boolean>> futures = new ArrayList<>();
    for (int i = 0; i < numberOfThread; i++) {
        // testNG won't be able to "know" if a child thread's assertion is false, so to get around it we
        // need to throw an exception so executorService can notify the main thread about the false assertion
        // even though executorService has an invokeAll method, it doesn't seem run the threads at the same time
        // so we have to use a latch to make sure all the threads run at the same time to simulate concurrent access
        Future<Boolean> future = executorService.submit(new Runnable() {

            @Override
            public void run() {
                startLatch.countDown();
                try {
                    // wait until all threads are ready to run together
                    startLatch.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException("Failed the test because thread was interrupted");
                }
                // if config is broken, every thread would fail and state update would be unsuccessful
                try {
                    TrackerClient resultTC = getTrackerClient(strategyAdapter, null, new RequestContext(), 1, clients);
                    if (trackerClientMustNotBeNull && resultTC == null) {
                        throw new RuntimeException("Failed the test because resultTC returns null");
                    }
                } catch (DummyException ex) {
                // expected
                }
                exitLatch.countDown();
                try {
                    // make sure all threads are not stuck on WAIT_THREAD
                    if (!exitLatch.await(5, TimeUnit.SECONDS)) {
                        throw new RuntimeException("Failed the test because we waited longer than 1 second");
                    }
                } catch (InterruptedException e) {
                    throw new RuntimeException("Failed the test because thread was interrupted");
                }
            }
        }, Boolean.TRUE);
        futures.add(future);
    }
    for (Future<Boolean> future : futures) {
        try {
            assertTrue(future.get());
        } catch (Exception e) {
            fail("something is failing", e);
        }
    }
    executorService.shutdownNow();
}
Also used : ArrayList(java.util.ArrayList) CountDownLatch(java.util.concurrent.CountDownLatch) URISyntaxException(java.net.URISyntaxException) TimeoutException(java.util.concurrent.TimeoutException) ExecutionException(java.util.concurrent.ExecutionException) DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient) TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) ExecutorService(java.util.concurrent.ExecutorService) Future(java.util.concurrent.Future) RequestContext(com.linkedin.r2.message.RequestContext) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean)

Example 27 with DegraderTrackerClient

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

the class DegraderLoadBalancerTest method stressTest.

@Test(groups = { "small", "back-end" })
public void stressTest() {
    final DegraderLoadBalancerStrategyV3 strategyV3 = getStrategy();
    TestClock testClock = new TestClock();
    String baseUri = "http://linkedin.com:9999";
    int numberOfPartitions = 10;
    Map<String, String> degraderProperties = new HashMap<>();
    degraderProperties.put(PropertyKeys.DEGRADER_HIGH_ERROR_RATE, "0.5");
    degraderProperties.put(PropertyKeys.DEGRADER_LOW_ERROR_RATE, "0.2");
    DegraderImpl.Config degraderConfig = DegraderConfigFactory.toDegraderConfig(degraderProperties);
    final List<DegraderTrackerClient> clients = new ArrayList<>();
    for (int i = 0; i < numberOfPartitions; i++) {
        URI uri = URI.create(baseUri + i);
        DegraderTrackerClient client = new DegraderTrackerClientImpl(uri, getDefaultPartitionData(1, numberOfPartitions), new TestLoadBalancerClient(uri), testClock, degraderConfig);
        clients.add(client);
    }
    final ExecutorService executor = Executors.newFixedThreadPool(100);
    final CountDownLatch startLatch = new CountDownLatch(1);
    final CountDownLatch finishLatch = new CountDownLatch(100);
    try {
        for (int i = 0; i < numberOfPartitions; i++) {
            Assert.assertFalse(strategyV3.getState().getPartitionState(i).isInitialized());
        }
        for (int i = 0; i < 100; i++) {
            final int partitionId = i % numberOfPartitions;
            executor.submit(new Runnable() {

                @Override
                public void run() {
                    try {
                        startLatch.await();
                    } catch (InterruptedException ex) {
                    }
                    strategyV3.getRing(1, partitionId, toMap(clients));
                    finishLatch.countDown();
                }
            });
        }
        // all threads would try to getRing simultanously
        startLatch.countDown();
        if (!finishLatch.await(10, TimeUnit.SECONDS)) {
            fail("Stress test failed to finish within 10 seconds");
        }
        for (int i = 0; i < numberOfPartitions; i++) {
            Assert.assertTrue(strategyV3.getState().getPartitionState(i).isInitialized());
        }
    } catch (InterruptedException ex) {
    } finally {
        executor.shutdownNow();
    }
}
Also used : HashMap(java.util.HashMap) DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient) DegraderImpl(com.linkedin.util.degrader.DegraderImpl) ArrayList(java.util.ArrayList) CountDownLatch(java.util.concurrent.CountDownLatch) URI(java.net.URI) ExecutorService(java.util.concurrent.ExecutorService) DegraderTrackerClientImpl(com.linkedin.d2.balancer.clients.DegraderTrackerClientImpl) Test(org.testng.annotations.Test) DegraderTrackerClientTest(com.linkedin.d2.balancer.clients.DegraderTrackerClientTest)

Example 28 with DegraderTrackerClient

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

the class DegraderLoadBalancerTest method testWeightedAndLatencyDegradationBalancingRing.

@Test(groups = { "small", "back-end" }, dataProvider = "consistentHashAlgorithms")
public void testWeightedAndLatencyDegradationBalancingRing(String consistentHashAlgorithm) throws URISyntaxException {
    DegraderLoadBalancerStrategyV3 strategy = getStrategy(consistentHashAlgorithm);
    List<DegraderTrackerClient> clients = new ArrayList<>();
    URI uri1 = URI.create("http://test.linkedin.com:3242/fdsaf");
    URI uri2 = URI.create("http://test.linkedin.com:3243/fdsaf");
    TestClock clock1 = new TestClock();
    TestClock clock2 = new TestClock();
    DegraderTrackerClient client1 = new DegraderTrackerClientImpl(uri1, getDefaultPartitionData(1d), new TestLoadBalancerClient(uri1), clock1, null);
    DegraderTrackerClient client2 = new DegraderTrackerClientImpl(uri2, getDefaultPartitionData(0.8d), new TestLoadBalancerClient(uri2), clock2, null);
    clients.add(client1);
    clients.add(client2);
    DegraderControl dcClient2Default = client2.getDegraderControl(DEFAULT_PARTITION_ID);
    dcClient2Default.setOverrideMinCallCount(1);
    dcClient2Default.setMinCallCount(1);
    dcClient2Default.setMaxDropRate(1d);
    dcClient2Default.setUpStep(0.4d);
    dcClient2Default.setHighErrorRate(0);
    CallCompletion cc = client2.getCallTracker().startCall();
    clock2.addMs(1);
    cc.endCallWithError();
    clock1.addMs(15000);
    clock2.addMs(5000);
    // trigger a state update
    assertNotNull(getTrackerClient(strategy, null, new RequestContext(), 1, clients));
    // now do a basic verification to verify getTrackerClient is properly weighting things
    double calls = 10000d;
    int client1Count = 0;
    int client2Count = 0;
    double tolerance = 0.05d;
    for (int i = 0; i < calls; ++i) {
        TrackerClient client = getTrackerClient(strategy, null, new RequestContext(), 1, clients);
        assertNotNull(client);
        if (client.getUri().equals(uri1)) {
            ++client1Count;
        } else {
            ++client2Count;
        }
    }
    assertTrue(Math.abs((client1Count / calls) - (100 / 148d)) < tolerance);
    assertTrue(Math.abs((client2Count / calls) - (48 / 148d)) < tolerance);
}
Also used : DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient) ArrayList(java.util.ArrayList) DegraderControl(com.linkedin.util.degrader.DegraderControl) URI(java.net.URI) CallCompletion(com.linkedin.util.degrader.CallCompletion) DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient) TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) DegraderTrackerClientImpl(com.linkedin.d2.balancer.clients.DegraderTrackerClientImpl) RequestContext(com.linkedin.r2.message.RequestContext) Test(org.testng.annotations.Test) DegraderTrackerClientTest(com.linkedin.d2.balancer.clients.DegraderTrackerClientTest)

Example 29 with DegraderTrackerClient

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

the class DegraderLoadBalancerTest method testRandom.

@Test(groups = { "small", "back-end" })
public void testRandom() throws URISyntaxException {
    DegraderLoadBalancerStrategyV3 strategy = getStrategy();
    List<DegraderTrackerClient> clients = new ArrayList<>();
    URI uri1 = URI.create("http://test.linkedin.com:3242/fdsaf");
    URI uri2 = URI.create("http://test.linkedin.com:3243/fdsaf");
    clients.add(getClient(uri1, new TestClock()));
    clients.add(getClient(uri2, new TestClock()));
    // since cluster call count is 0, we will default to random
    for (int i = 0; i < 1000; ++i) {
        TrackerClient client = getTrackerClient(strategy, null, new RequestContext(), 0, clients);
        assertNotNull(client);
        assertTrue(clients.contains(client));
    }
}
Also used : DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient) TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient) ArrayList(java.util.ArrayList) RequestContext(com.linkedin.r2.message.RequestContext) URI(java.net.URI) Test(org.testng.annotations.Test) DegraderTrackerClientTest(com.linkedin.d2.balancer.clients.DegraderTrackerClientTest)

Example 30 with DegraderTrackerClient

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

the class DegraderLoadBalancerTest method testInconsistentHashAndTrackerclients.

@Test(groups = { "small", "back-end" }, dataProvider = "consistentHashAlgorithms")
public void testInconsistentHashAndTrackerclients(String consistentHashAlgorithm) throws URISyntaxException, InterruptedException {
    // check if the inconsistent Hash ring and trackerlients can be handled
    TestClock clock = new TestClock();
    Map<String, Object> myMap = lbDefaultConfig();
    myMap.put(PropertyKeys.CLOCK, clock);
    myMap.put(PropertyKeys.HTTP_LB_CONSISTENT_HASH_ALGORITHM, consistentHashAlgorithm);
    DegraderLoadBalancerStrategyConfig config = DegraderLoadBalancerStrategyConfig.createHttpConfigFromMap(myMap);
    DegraderLoadBalancerStrategyV3 strategy = new DegraderLoadBalancerStrategyV3(config, "DegraderLoadBalancerTest", null, DEGRADER_STATE_LISTENER_FACTORIES);
    List<DegraderTrackerClient> clients = new ArrayList<>();
    clients.add(getClient(URI.create("http://test.linkedin.com:3242/fdsaf"), clock));
    clients.add(getClient(URI.create("http://test.linkedin.com:3243/fdsaf"), clock));
    TrackerClient chosen = getTrackerClient(strategy, null, new RequestContext(), 0, clients);
    assertNotNull(chosen);
    // remove the client from the list, now the ring and the trackerClient list are inconsistent
    clients.remove(chosen);
    assertNotNull(getTrackerClient(strategy, null, new RequestContext(), 0, clients));
    // update the hash ring we should get the results as well
    assertNotNull(getTrackerClient(strategy, null, new RequestContext(), 1, clients));
}
Also used : DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient) TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient) ArrayList(java.util.ArrayList) RequestContext(com.linkedin.r2.message.RequestContext) Test(org.testng.annotations.Test) DegraderTrackerClientTest(com.linkedin.d2.balancer.clients.DegraderTrackerClientTest)

Aggregations

DegraderTrackerClient (com.linkedin.d2.balancer.clients.DegraderTrackerClient)58 Test (org.testng.annotations.Test)46 DegraderTrackerClientTest (com.linkedin.d2.balancer.clients.DegraderTrackerClientTest)42 ArrayList (java.util.ArrayList)34 URI (java.net.URI)31 RequestContext (com.linkedin.r2.message.RequestContext)30 TrackerClient (com.linkedin.d2.balancer.clients.TrackerClient)20 DegraderImpl (com.linkedin.util.degrader.DegraderImpl)19 AtomicLong (java.util.concurrent.atomic.AtomicLong)17 DegraderControl (com.linkedin.util.degrader.DegraderControl)16 HashMap (java.util.HashMap)16 DegraderTrackerClientImpl (com.linkedin.d2.balancer.clients.DegraderTrackerClientImpl)14 CallCompletion (com.linkedin.util.degrader.CallCompletion)11 URIRequest (com.linkedin.d2.balancer.util.URIRequest)9 PartitionData (com.linkedin.d2.balancer.properties.PartitionData)7 SettableClock (com.linkedin.util.clock.SettableClock)6 LoadBalancerQuarantine (com.linkedin.d2.balancer.strategies.LoadBalancerQuarantine)4 RestRequest (com.linkedin.r2.message.rest.RestRequest)4 CountDownLatch (java.util.concurrent.CountDownLatch)4 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)4