Search in sources :

Example 26 with DegraderLoadBalancerStrategyV3

use of com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerStrategyV3 in project rest.li by linkedin.

the class DegraderLoadBalancerTest method testRegexHashingConsistency.

@Test(groups = { "small", "back-end" })
public void testRegexHashingConsistency() {
    final int NUM_SERVERS = 100;
    DegraderLoadBalancerStrategyV3 strategy = new DegraderLoadBalancerStrategyV3(new DegraderLoadBalancerStrategyConfig(5000, true, 100, DegraderLoadBalancerStrategyV3.HASH_METHOD_URI_REGEX, Collections.<String, Object>singletonMap(URIRegexHash.KEY_REGEXES, Collections.singletonList("(.*)")), SystemClock.instance(), DegraderLoadBalancerStrategyConfig.DEFAULT_INITIAL_RECOVERY_LEVEL, DegraderLoadBalancerStrategyConfig.DEFAULT_RAMP_FACTOR, DegraderLoadBalancerStrategyConfig.DEFAULT_HIGH_WATER_MARK, DegraderLoadBalancerStrategyConfig.DEFAULT_LOW_WATER_MARK, DegraderLoadBalancerStrategyConfig.DEFAULT_GLOBAL_STEP_UP, DegraderLoadBalancerStrategyConfig.DEFAULT_GLOBAL_STEP_DOWN, DegraderLoadBalancerStrategyConfig.DEFAULT_CLUSTER_MIN_CALL_COUNT_HIGH_WATER_MARK, DegraderLoadBalancerStrategyConfig.DEFAULT_CLUSTER_MIN_CALL_COUNT_LOW_WATER_MARK, DegraderLoadBalancerStrategyConfig.DEFAULT_HASHRING_POINT_CLEANUP_RATE, null, DegraderLoadBalancerStrategyConfig.DEFAULT_NUM_PROBES, null, DegraderLoadBalancerStrategyConfig.DEFAULT_QUARANTINE_MAXPERCENT, null, null, DegraderLoadBalancerStrategyConfig.DEFAULT_QUARANTINE_METHOD, null, DegraderLoadBalancerStrategyConfig.DEFAULT_QUARANTINE_LATENCY), "DegraderLoadBalancerTest", null);
    List<TrackerClient> clients = new ArrayList<TrackerClient>(NUM_SERVERS);
    for (int i = 0; i < NUM_SERVERS; i++) {
        clients.add(getClient(URI.create("http://server" + i + ".testing:9876/foobar")));
    }
    final int NUM_URIS = 1000;
    final int NUM_CHECKS = 10;
    final Map<TrackerClient, Integer> serverCounts = new HashMap<TrackerClient, Integer>();
    for (int i = 0; i < NUM_URIS; i++) {
        URIRequest request = new URIRequest("d2://fooService/this/is/a/test/" + i);
        TrackerClient lastClient = null;
        for (int j = 0; j < NUM_CHECKS; j++) {
            TrackerClient client = getTrackerClient(strategy, request, new RequestContext(), 0, clients);
            assertNotNull(client);
            if (lastClient != null) {
                assertEquals(client, lastClient);
            }
            lastClient = client;
        }
        Integer count = serverCounts.get(lastClient);
        if (count == null) {
            count = 0;
        }
        serverCounts.put(lastClient, count + 1);
    }
// TODO... should check the distribution of hits/server, should be pretty even, but how
// even is even?  Also note this depends on pointsPerServer and other configurable parameters.
// TODO... another test will check that when a TrackerClient is removed, the distribution
// doesn't change too much.
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) URIRequest(com.linkedin.d2.balancer.util.URIRequest) TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) RequestContext(com.linkedin.r2.message.RequestContext) Test(org.testng.annotations.Test) TrackerClientTest(com.linkedin.d2.balancer.clients.TrackerClientTest)

Example 27 with DegraderLoadBalancerStrategyV3

use of com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerStrategyV3 in project rest.li by linkedin.

the class DegraderLoadBalancerTest method testWeightedAndLatencyDegradationBalancingRingWithPartitions.

@Test(groups = { "small", "back-end" }, dataProvider = "consistentHashAlgorithms")
public void testWeightedAndLatencyDegradationBalancingRingWithPartitions(String consistentHashAlgorithm) throws URISyntaxException {
    DegraderLoadBalancerStrategyV3 strategy = getStrategy(consistentHashAlgorithm);
    List<TrackerClient> clientsForPartition0 = new ArrayList<TrackerClient>();
    List<TrackerClient> clientsForPartition1 = new ArrayList<TrackerClient>();
    URI uri1 = URI.create("http://someTestService/someTestUrl");
    URI uri2 = URI.create("http://abcxfweuoeueoueoueoukeueoueoueoueoueouo/2354");
    URI uri3 = URI.create("http://slashdot/blah");
    URI uri4 = URI.create("http://idle/server");
    TestClock clock1 = new TestClock();
    TestClock clock2 = new TestClock();
    TestClock clock3 = new TestClock();
    @SuppressWarnings("serial") TrackerClient client1 = new TrackerClient(uri1, new HashMap<Integer, PartitionData>() {

        {
            put(0, new PartitionData(1d));
        }
    }, new TestLoadBalancerClient(uri1), clock1, null);
    @SuppressWarnings("serial") TrackerClient client2 = new TrackerClient(uri2, new HashMap<Integer, PartitionData>() {

        {
            put(0, new PartitionData(0.5d));
            put(1, new PartitionData(0.5d));
        }
    }, new TestLoadBalancerClient(uri2), clock2, null);
    @SuppressWarnings("serial") TrackerClient client3 = new TrackerClient(uri3, new HashMap<Integer, PartitionData>() {

        {
            put(1, new PartitionData(1d));
        }
    }, new TestLoadBalancerClient(uri3), clock3, null);
    final int partitionId0 = 0;
    clientsForPartition0.add(client1);
    clientsForPartition0.add(client2);
    final int partitionId1 = 1;
    clientsForPartition1.add(client2);
    clientsForPartition1.add(client3);
    // force client2 to be disabled
    DegraderControl dcClient2Partition0 = client2.getDegraderControl(0);
    DegraderControl dcClient2Partition1 = client2.getDegraderControl(1);
    dcClient2Partition0.setOverrideMinCallCount(1);
    dcClient2Partition0.setMinCallCount(1);
    dcClient2Partition0.setMaxDropRate(1d);
    dcClient2Partition0.setUpStep(0.4d);
    dcClient2Partition0.setHighErrorRate(0);
    dcClient2Partition1.setOverrideMinCallCount(1);
    dcClient2Partition1.setMinCallCount(1);
    dcClient2Partition1.setMaxDropRate(1d);
    dcClient2Partition1.setUpStep(0.4d);
    dcClient2Partition1.setHighErrorRate(0);
    CallCompletion cc = client2.getCallTracker().startCall();
    clock2.addMs(1);
    cc.endCallWithError();
    // force client3 to be disabled
    DegraderControl dcClient3Partition1 = client3.getDegraderControl(1);
    dcClient3Partition1.setOverrideMinCallCount(1);
    dcClient3Partition1.setMinCallCount(1);
    dcClient3Partition1.setMaxDropRate(1d);
    dcClient3Partition1.setHighErrorRate(0);
    dcClient3Partition1.setUpStep(0.2d);
    CallCompletion cc3 = client3.getCallTracker().startCall();
    clock3.addMs(1);
    cc3.endCallWithError();
    clock1.addMs(15000);
    clock2.addMs(5000);
    clock3.addMs(5000);
    // trigger a state update
    assertNotNull(strategy.getTrackerClient(null, new RequestContext(), 1, partitionId0, clientsForPartition0));
    assertNotNull(strategy.getTrackerClient(null, new RequestContext(), 1, partitionId1, clientsForPartition1));
    assertNotNull(strategy.getRing(1, partitionId0, clientsForPartition0));
    assertNotNull(strategy.getRing(1, partitionId1, clientsForPartition1));
    // now do a basic verification to verify getTrackerClient is properly weighting things
    int calls = 10000;
    int client1Count = 0;
    int client2Count = 0;
    double tolerance = 0.05d;
    for (int i = 0; i < calls; ++i) {
        TrackerClient client = strategy.getTrackerClient(null, new RequestContext(), 1, partitionId0, clientsForPartition0);
        assertNotNull(client);
        if (client.getUri().equals(uri1)) {
            ++client1Count;
        } else {
            ++client2Count;
        }
    }
    assertTrue(Math.abs((client1Count / (double) calls) - (100 / 130d)) < tolerance);
    assertTrue(Math.abs((client2Count / (double) calls) - (30 / 130d)) < tolerance);
    client2Count = 0;
    int client3Count = 0;
    int client4Count = 0;
    for (int i = 0; i < calls; ++i) {
        TrackerClient client = strategy.getTrackerClient(null, new RequestContext(), 1, partitionId1, clientsForPartition1);
        assertNotNull(client);
        if (client.getUri().equals(uri3)) {
            ++client3Count;
        } else if (client.getUri().equals(uri2)) {
            ++client2Count;
        } else {
            ++client4Count;
        }
    }
    assertTrue(Math.abs((client3Count / (double) calls) - (80 / 110d)) < tolerance);
    assertTrue(Math.abs((client2Count / (double) calls) - (30 / 110d)) < tolerance);
    assertTrue(client4Count == 0);
}
Also used : ArrayList(java.util.ArrayList) DegraderControl(com.linkedin.util.degrader.DegraderControl) URI(java.net.URI) TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) CallCompletion(com.linkedin.util.degrader.CallCompletion) PartitionData(com.linkedin.d2.balancer.properties.PartitionData) RequestContext(com.linkedin.r2.message.RequestContext) Test(org.testng.annotations.Test) TrackerClientTest(com.linkedin.d2.balancer.clients.TrackerClientTest)

Example 28 with DegraderLoadBalancerStrategyV3

use of com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerStrategyV3 in project rest.li by linkedin.

the class DegraderLoadBalancerTest method testStateIsNotNullAndCallCountIsZero.

@Test(groups = { "small", "back-end" })
public void testStateIsNotNullAndCallCountIsZero() throws URISyntaxException {
    DegraderLoadBalancerStrategyV3 strategy = new DegraderLoadBalancerStrategyV3(new DegraderLoadBalancerStrategyConfig(5000), "DegraderLoadBalancerTest", null);
    List<TrackerClient> clients = new ArrayList<TrackerClient>();
    SettableClock clock1 = new SettableClock();
    SettableClock clock2 = new SettableClock();
    clients.add(getClient(URI.create("http://test.linkedin.com:3242/fdsaf"), clock1));
    clients.add(getClient(URI.create("http://test.linkedin.com:3243/fdsaf"), clock2));
    clock1.addDuration(5000);
    // this should trigger setting _state (generation id is different) with an override
    // of 0d
    getTrackerClient(strategy, null, new RequestContext(), 0, clients);
    // should not have overridden anything, and default is 0
    for (TrackerClient client : clients) {
        assertEquals(client.getDegraderControl(DEFAULT_PARTITION_ID).getOverrideDropRate(), 0d);
    }
    // this should trigger setting _state (state is null and count > 0) with an override
    // of 0d
    assertNotNull(getTrackerClient(strategy, null, new RequestContext(), -1, clients));
}
Also used : TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) ArrayList(java.util.ArrayList) SettableClock(com.linkedin.util.clock.SettableClock) RequestContext(com.linkedin.r2.message.RequestContext) Test(org.testng.annotations.Test) TrackerClientTest(com.linkedin.d2.balancer.clients.TrackerClientTest)

Example 29 with DegraderLoadBalancerStrategyV3

use of com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerStrategyV3 in project rest.li by linkedin.

the class DegraderLoadBalancerTest method createRaceCondition.

private List<Runnable> createRaceCondition(final URI uri, Clock clock, final DegraderLoadBalancerStrategyV3 strategy, final CountDownLatch joinLatch) {
    final CountDownLatch clientLatch = new CountDownLatch(1);
    TrackerClient evilClient = new EvilClient(uri, getDefaultPartitionData(1, 2), new TrackerClientTest.TestClient(), clock, null, clientLatch);
    final List<TrackerClient> clients = Collections.singletonList(evilClient);
    final Runnable update = new Runnable() {

        @Override
        public void run() {
            // getRing will wait for latch in getPartitionWeight
            strategy.getRing(1, 0, clients);
            joinLatch.countDown();
        }
    };
    final Runnable resize = new Runnable() {

        @Override
        public void run() {
            // releases latch for partition 0
            clientLatch.countDown();
            // resize
            strategy.getRing(1, 1, clients);
            joinLatch.countDown();
        }
    };
    List<Runnable> actions = new ArrayList<Runnable>();
    actions.add(update);
    actions.add(resize);
    return actions;
}
Also used : TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) TrackerClientTest(com.linkedin.d2.balancer.clients.TrackerClientTest) ArrayList(java.util.ArrayList) CountDownLatch(java.util.concurrent.CountDownLatch)

Example 30 with DegraderLoadBalancerStrategyV3

use of com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerStrategyV3 in project rest.li by linkedin.

the class DegraderLoadBalancerTest method testOverrideClusterDropRate.

@Test(groups = { "small", "back-end" })
public void testOverrideClusterDropRate() throws URISyntaxException {
    DegraderLoadBalancerStrategyV3 strategy = getStrategy();
    List<TrackerClient> clients = new ArrayList<TrackerClient>();
    List<TrackerClientUpdater> clientUpdaters = new ArrayList<TrackerClientUpdater>();
    for (TrackerClient client : clients) {
        clientUpdaters.add(new TrackerClientUpdater(client, DEFAULT_PARTITION_ID));
    }
    clients.add(getClient(URI.create("http://test.linkedin.com:3242/fdsaf")));
    clients.add(getClient(URI.create("http://test.linkedin.com:3243/fdsaf")));
    DegraderLoadBalancerStrategyV3.overrideClusterDropRate(DEFAULT_PARTITION_ID, 1d, clientUpdaters);
    for (TrackerClientUpdater clientUpdater : clientUpdaters) {
        TrackerClient client = clientUpdater.getTrackerClient();
        clientUpdater.update();
        assertEquals(client.getDegraderControl(DEFAULT_PARTITION_ID).getOverrideDropRate(), 1d);
        assertTrue(client.getDegrader(DEFAULT_PARTITION_ID).checkDrop());
    }
    DegraderLoadBalancerStrategyV3.overrideClusterDropRate(DEFAULT_PARTITION_ID, -1d, clientUpdaters);
    // if we don't override, the degrader isn't degraded, so should not drop
    for (TrackerClientUpdater clientUpdater : clientUpdaters) {
        TrackerClient client = clientUpdater.getTrackerClient();
        clientUpdater.update();
        assertEquals(client.getDegraderControl(DEFAULT_PARTITION_ID).getOverrideDropRate(), -1d);
        assertFalse(client.getDegrader(DEFAULT_PARTITION_ID).checkDrop());
    }
    DegraderLoadBalancerStrategyV3.overrideClusterDropRate(DEFAULT_PARTITION_ID, 0d, clientUpdaters);
    for (TrackerClientUpdater clientUpdater : clientUpdaters) {
        TrackerClient client = clientUpdater.getTrackerClient();
        clientUpdater.update();
        assertEquals(client.getDegraderControl(DEFAULT_PARTITION_ID).getOverrideDropRate(), 0d);
        assertFalse(client.getDegrader(DEFAULT_PARTITION_ID).checkDrop());
    }
}
Also used : TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) ArrayList(java.util.ArrayList) Test(org.testng.annotations.Test) TrackerClientTest(com.linkedin.d2.balancer.clients.TrackerClientTest)

Aggregations

Test (org.testng.annotations.Test)45 TrackerClientTest (com.linkedin.d2.balancer.clients.TrackerClientTest)41 TrackerClient (com.linkedin.d2.balancer.clients.TrackerClient)38 HashMap (java.util.HashMap)33 ArrayList (java.util.ArrayList)32 RequestContext (com.linkedin.r2.message.RequestContext)23 URI (java.net.URI)21 AtomicLong (java.util.concurrent.atomic.AtomicLong)18 DegraderImpl (com.linkedin.util.degrader.DegraderImpl)13 CallCompletion (com.linkedin.util.degrader.CallCompletion)9 DegraderControl (com.linkedin.util.degrader.DegraderControl)9 URIRequest (com.linkedin.d2.balancer.util.URIRequest)5 CountDownLatch (java.util.concurrent.CountDownLatch)5 PartitionData (com.linkedin.d2.balancer.properties.PartitionData)4 DegraderLoadBalancerStrategyV3 (com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerStrategyV3)4 com.linkedin.d2.hashConfigType (com.linkedin.d2.hashConfigType)3 com.linkedin.d2.quarantineInfo (com.linkedin.d2.quarantineInfo)3 Map (java.util.Map)3 ExecutorService (java.util.concurrent.ExecutorService)3 D2LoadBalancerStrategyProperties (com.linkedin.d2.D2LoadBalancerStrategyProperties)2