Search in sources :

Example 16 with DegraderLoadBalancerStrategyConfig

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

the class DegraderLoadBalancerTest method testClusterRecovery2TC.

@Test(groups = { "small", "back-end" })
public void testClusterRecovery2TC() {
    final int NUM_CHECKS = 5;
    final Long TIME_INTERVAL = 5000L;
    Map<String, Object> myMap = new HashMap<String, Object>();
    // 1,2,4,8,16,32,64,100% steps, given a 2x recovery step coefficient
    int localStepsToFullRecovery = 8;
    myMap.put(PropertyKeys.HTTP_LB_INITIAL_RECOVERY_LEVEL, 0.005);
    myMap.put(PropertyKeys.HTTP_LB_RING_RAMP_FACTOR, 2d);
    myMap.put(PropertyKeys.HTTP_LB_STRATEGY_PROPERTIES_UPDATE_INTERVAL_MS, TIME_INTERVAL);
    TestClock clock = new TestClock();
    myMap.put(PropertyKeys.CLOCK, clock);
    DegraderLoadBalancerStrategyConfig config = DegraderLoadBalancerStrategyConfig.createHttpConfigFromMap(myMap);
    DegraderLoadBalancerStrategyV3 strategy = new DegraderLoadBalancerStrategyV3(config, "DegraderLoadBalancerTest", null);
    List<TrackerClient> clients = new ArrayList<TrackerClient>();
    URI uri1 = URI.create("http://test.linkedin.com:3242/fdsaf");
    URI uri2 = URI.create("http://test.linkedin.com:3243/fdsaf");
    URIRequest request = new URIRequest(uri1);
    List<CallCompletion> ccList = new ArrayList<CallCompletion>();
    CallCompletion cc;
    TrackerClient client1 = new TrackerClient(uri1, getDefaultPartitionData(1d), new TestLoadBalancerClient(uri1), clock, null);
    TrackerClient client2 = new TrackerClient(uri2, getDefaultPartitionData(1d), new TestLoadBalancerClient(uri2), clock, null);
    clients.add(client1);
    clients.add(client2);
    // force client1 to be disabled if we encounter errors/high latency
    DegraderControl dcClient1Default = client1.getDegraderControl(DEFAULT_PARTITION_ID);
    dcClient1Default.setMinCallCount(5);
    dcClient1Default.setOverrideMinCallCount(5);
    dcClient1Default.setUpStep(1.0);
    // force client2 to be disabled if we encounter errors/high latency
    DegraderControl dcClient2Default = client2.getDegraderControl(DEFAULT_PARTITION_ID);
    dcClient2Default.setOverrideMinCallCount(5);
    dcClient2Default.setMinCallCount(5);
    dcClient2Default.setUpStep(0.4);
    // Have one cycle of successful calls to verify valid tracker clients returned.
    // try load balancing on this updateState, need to updateState before forcing the strategy.
    TrackerClient resultTC = getTrackerClient(strategy, request, new RequestContext(), 1, clients);
    strategy.setStrategy(DEFAULT_PARTITION_ID, DegraderLoadBalancerStrategyV3.PartitionDegraderLoadBalancerState.Strategy.LOAD_BALANCE);
    resultTC = getTrackerClient(strategy, request, new RequestContext(), 1, clients);
    assertNotNull(resultTC, "expected non-null trackerclient");
    for (int j = 0; j < NUM_CHECKS; j++) {
        ccList.add(client1.getCallTracker().startCall());
        ccList.add(client2.getCallTracker().startCall());
    }
    clock.addMs(1);
    for (Iterator<CallCompletion> iter = ccList.listIterator(); iter.hasNext(); ) {
        cc = iter.next();
        cc.endCall();
    }
    // bump to next interval, and get stats.
    clock.addMs(5000);
    // try Load balancing on this updateState
    strategy.setStrategy(DEFAULT_PARTITION_ID, DegraderLoadBalancerStrategyV3.PartitionDegraderLoadBalancerState.Strategy.LOAD_BALANCE);
    resultTC = getTrackerClient(strategy, request, new RequestContext(), 1, clients);
    assertNotNull(resultTC, "expected non-null trackerclient");
    Assert.assertEquals(dcClient1Default.getCurrentComputedDropRate(), 0.0);
    Assert.assertEquals(dcClient2Default.getCurrentComputedDropRate(), 0.0);
    // now simulate a bad cluster state with high error and high latency
    for (int j = 0; j < NUM_CHECKS; j++) {
        ccList.add(client1.getCallTracker().startCall());
        ccList.add(client2.getCallTracker().startCall());
    }
    clock.addMs(3500);
    for (Iterator<CallCompletion> iter = ccList.listIterator(); iter.hasNext(); ) {
        cc = iter.next();
        cc.endCallWithError();
    }
    // go to next interval
    clock.addMs(5000);
    Assert.assertEquals(dcClient1Default.getCurrentComputedDropRate(), 1.0);
    Assert.assertEquals(dcClient2Default.getCurrentComputedDropRate(), 0.4);
    // trigger a state update, the returned TrackerClient should be client2
    // because client 1 should have gone up to a 1.0 drop rate, and the cluster should
    // be unhealthy
    strategy.setStrategy(DEFAULT_PARTITION_ID, DegraderLoadBalancerStrategyV3.PartitionDegraderLoadBalancerState.Strategy.LOAD_BALANCE);
    resultTC = getTrackerClient(strategy, request, new RequestContext(), 1, clients);
    assertEquals(resultTC, client2);
    // it's current drop rate.
    do {
        // go to next time interval.
        clock.addMs(TIME_INTERVAL);
        // adjust the hash ring this time.
        strategy.setStrategy(DEFAULT_PARTITION_ID, DegraderLoadBalancerStrategyV3.PartitionDegraderLoadBalancerState.Strategy.LOAD_BALANCE);
        resultTC = getTrackerClient(strategy, request, new RequestContext(), 1, clients);
        localStepsToFullRecovery--;
    } while (localStepsToFullRecovery > 0);
    assertNotNull(resultTC, "expected non-null trackerclient");
    assertTrue(strategy.getState().getPartitionState(DEFAULT_PARTITION_ID).getPointsMap().get(client1.getUri()) == client1.getPartitionWeight(DEFAULT_PARTITION_ID) * config.getPointsPerWeight(), "client1 did not recover to full weight in hash map.");
    Assert.assertEquals(dcClient2Default.getCurrentComputedDropRate(), 0.4, "client2 drop rate not as expected");
    cc = client1.getCallTracker().startCall();
    clock.addMs(10);
    cc.endCall();
    clock.addMs(TIME_INTERVAL);
    resultTC = getTrackerClient(strategy, request, new RequestContext(), 1, clients);
    assertNotNull(resultTC, "expected non-null trackerclient");
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) URIRequest(com.linkedin.d2.balancer.util.URIRequest) DegraderControl(com.linkedin.util.degrader.DegraderControl) URI(java.net.URI) TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) CallCompletion(com.linkedin.util.degrader.CallCompletion) AtomicLong(java.util.concurrent.atomic.AtomicLong) RequestContext(com.linkedin.r2.message.RequestContext) Test(org.testng.annotations.Test) TrackerClientTest(com.linkedin.d2.balancer.clients.TrackerClientTest)

Example 17 with DegraderLoadBalancerStrategyConfig

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

the class DegraderLoadBalancerTest method testStateIsNullAndCallCountIsGreaterThanZeroWithLatency.

@Test(groups = { "small", "back-end" })
public void testStateIsNullAndCallCountIsGreaterThanZeroWithLatency() throws URISyntaxException, InterruptedException {
    // check for average cluster latency < max latency
    // max so we don't time out from lag on testing machine
    DegraderLoadBalancerStrategyV3 strategy = new DegraderLoadBalancerStrategyV3(new DegraderLoadBalancerStrategyConfig(5000), "DegraderLoadBalancerTest", null);
    List<TrackerClient> clients = new ArrayList<TrackerClient>();
    TestClock clock1 = new TestClock();
    TestClock clock2 = new TestClock();
    clients.add(getClient(URI.create("http://test.linkedin.com:3242/fdsaf"), clock1));
    clients.add(getClient(URI.create("http://test.linkedin.com:3243/fdsaf"), clock2));
    for (int i = 0; i < 1000; ++i) {
        clients.get(i % 2).getCallTracker().startCall().endCall();
    }
    clock1.addMs(5000);
    // this should trigger setting _state (state is null and count > 0)
    getTrackerClient(strategy, null, new RequestContext(), -1, clients);
    // we chose to initialize the state first.
    for (TrackerClient client : clients) {
        assertEquals(client.getDegraderControl(DEFAULT_PARTITION_ID).getOverrideDropRate(), 0.0);
    }
}
Also used : TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) ArrayList(java.util.ArrayList) RequestContext(com.linkedin.r2.message.RequestContext) Test(org.testng.annotations.Test) TrackerClientTest(com.linkedin.d2.balancer.clients.TrackerClientTest)

Example 18 with DegraderLoadBalancerStrategyConfig

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

the class DegraderLoadBalancerTest method testHighTrafficHighLatency1Client.

@Test(groups = { "small", "back-end" })
public void testHighTrafficHighLatency1Client() {
    Map<String, Object> myMap = new HashMap<String, Object>();
    Long timeInterval = 5000L;
    TestClock clock = new TestClock();
    myMap.put(PropertyKeys.CLOCK, clock);
    myMap.put(PropertyKeys.HTTP_LB_STRATEGY_PROPERTIES_UPDATE_INTERVAL_MS, timeInterval);
    Map<String, String> degraderProperties = new HashMap<String, String>();
    degraderProperties.put(PropertyKeys.DEGRADER_HIGH_ERROR_RATE, "0.5");
    degraderProperties.put(PropertyKeys.DEGRADER_LOW_ERROR_RATE, "0.2");
    DegraderImpl.Config degraderConfig = DegraderConfigFactory.toDegraderConfig(degraderProperties);
    double qps = 121;
    //test Strategy V3
    List<TrackerClient> clients = createTrackerClient(1, clock, degraderConfig);
    DegraderLoadBalancerStrategyConfig config = DegraderLoadBalancerStrategyConfig.createHttpConfigFromMap(myMap);
    DegraderLoadBalancerStrategyV3 strategyV3 = new DegraderLoadBalancerStrategyV3(config, "DegraderLoadBalancerTest", null);
    DegraderLoadBalancerStrategyAdapter strategy = new DegraderLoadBalancerStrategyAdapter(strategyV3);
    testDegraderLoadBalancerSimulator(strategy, clock, timeInterval, clients, qps, degraderConfig);
    //test Strategy V2
    clients = createTrackerClient(1, clock, degraderConfig);
    config = DegraderLoadBalancerStrategyConfig.createHttpConfigFromMap(myMap);
    DegraderLoadBalancerStrategyV2_1 strategyV2 = new DegraderLoadBalancerStrategyV2_1(config, "DegraderLoadBalancerTest", null);
    strategy = new DegraderLoadBalancerStrategyAdapter(strategyV2);
    testDegraderLoadBalancerSimulator(strategy, clock, timeInterval, clients, qps, degraderConfig);
}
Also used : HashMap(java.util.HashMap) DegraderImpl(com.linkedin.util.degrader.DegraderImpl) TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) AtomicLong(java.util.concurrent.atomic.AtomicLong) Test(org.testng.annotations.Test) TrackerClientTest(com.linkedin.d2.balancer.clients.TrackerClientTest)

Example 19 with DegraderLoadBalancerStrategyConfig

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

the class DegraderLoadBalancerTest method testClusterRecoverySlow1TC.

@Test(groups = { "small", "back-end" })
public void testClusterRecoverySlow1TC() {
    Map<String, Object> myMap = new HashMap<String, Object>();
    Long timeInterval = 5000L;
    TestClock clock = new TestClock();
    myMap.put(PropertyKeys.CLOCK, clock);
    // We want the degrader to have one cooling off period, and then re-enter the ring. This
    myMap.put(PropertyKeys.HTTP_LB_INITIAL_RECOVERY_LEVEL, 0.005);
    myMap.put(PropertyKeys.HTTP_LB_RING_RAMP_FACTOR, 2.0);
    myMap.put(PropertyKeys.HTTP_LB_STRATEGY_PROPERTIES_UPDATE_INTERVAL_MS, timeInterval);
    // it will take two intervals for the TC to be reintroduced into the hash ring.
    int stepsToFullRecovery = 1;
    //test Strategy V3
    DegraderLoadBalancerStrategyConfig config = DegraderLoadBalancerStrategyConfig.createHttpConfigFromMap(myMap);
    DegraderLoadBalancerStrategyV3 strategyV3 = new DegraderLoadBalancerStrategyV3(config, "DegraderLoadBalancerTest", null);
    DegraderLoadBalancerStrategyAdapter strategy = new DegraderLoadBalancerStrategyAdapter(strategyV3);
    clusterRecovery1TC(myMap, clock, stepsToFullRecovery, timeInterval, strategy, null, DegraderLoadBalancerStrategyV3.PartitionDegraderLoadBalancerState.Strategy.LOAD_BALANCE);
    //test Strategy V2
    config = DegraderLoadBalancerStrategyConfig.createHttpConfigFromMap(myMap);
    DegraderLoadBalancerStrategyV2_1 strategyV2 = new DegraderLoadBalancerStrategyV2_1(config, "DegraderLoadBalancerTest", null);
    strategy = new DegraderLoadBalancerStrategyAdapter(strategyV2);
    clusterRecovery1TC(myMap, clock, stepsToFullRecovery, timeInterval, strategy, DegraderLoadBalancerStrategyV2_1.DegraderLoadBalancerState.Strategy.LOAD_BALANCE, null);
}
Also used : HashMap(java.util.HashMap) AtomicLong(java.util.concurrent.atomic.AtomicLong) Test(org.testng.annotations.Test) TrackerClientTest(com.linkedin.d2.balancer.clients.TrackerClientTest)

Example 20 with DegraderLoadBalancerStrategyConfig

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

the class DegraderLoadBalancerTest method testMediumTrafficHighLatency100Clients.

@Test(groups = { "small", "back-end" })
public void testMediumTrafficHighLatency100Clients() {
    Map<String, Object> myMap = new HashMap<String, Object>();
    Long timeInterval = 5000L;
    TestClock clock = new TestClock();
    myMap.put(PropertyKeys.CLOCK, clock);
    myMap.put(PropertyKeys.HTTP_LB_STRATEGY_PROPERTIES_UPDATE_INTERVAL_MS, timeInterval);
    myMap.put(PropertyKeys.HTTP_LB_STRATEGY_PROPERTIES_UPDATE_INTERVAL_MS, timeInterval);
    Map<String, String> degraderProperties = new HashMap<String, String>();
    degraderProperties.put(PropertyKeys.DEGRADER_HIGH_ERROR_RATE, "0.5");
    degraderProperties.put(PropertyKeys.DEGRADER_LOW_ERROR_RATE, "0.2");
    DegraderImpl.Config degraderConfig = DegraderConfigFactory.toDegraderConfig(degraderProperties);
    double qps = 7.3;
    //test Strategy V3
    List<TrackerClient> clients = createTrackerClient(100, clock, degraderConfig);
    DegraderLoadBalancerStrategyConfig config = DegraderLoadBalancerStrategyConfig.createHttpConfigFromMap(myMap);
    DegraderLoadBalancerStrategyV3 strategyV3 = new DegraderLoadBalancerStrategyV3(config, "DegraderLoadBalancerTest", null);
    DegraderLoadBalancerStrategyAdapter strategy = new DegraderLoadBalancerStrategyAdapter(strategyV3);
    testDegraderLoadBalancerSimulator(strategy, clock, timeInterval, clients, qps, degraderConfig);
    //test Strategy V2
    clients = createTrackerClient(100, clock, degraderConfig);
    config = DegraderLoadBalancerStrategyConfig.createHttpConfigFromMap(myMap);
    DegraderLoadBalancerStrategyV2_1 strategyV2 = new DegraderLoadBalancerStrategyV2_1(config, "DegraderLoadBalancerTest", null);
    strategy = new DegraderLoadBalancerStrategyAdapter(strategyV2);
    testDegraderLoadBalancerSimulator(strategy, clock, timeInterval, clients, qps, degraderConfig);
}
Also used : HashMap(java.util.HashMap) DegraderImpl(com.linkedin.util.degrader.DegraderImpl) TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) AtomicLong(java.util.concurrent.atomic.AtomicLong) Test(org.testng.annotations.Test) TrackerClientTest(com.linkedin.d2.balancer.clients.TrackerClientTest)

Aggregations

TrackerClient (com.linkedin.d2.balancer.clients.TrackerClient)34 HashMap (java.util.HashMap)28 Test (org.testng.annotations.Test)28 TrackerClientTest (com.linkedin.d2.balancer.clients.TrackerClientTest)24 ArrayList (java.util.ArrayList)19 AtomicLong (java.util.concurrent.atomic.AtomicLong)19 URI (java.net.URI)15 DegraderImpl (com.linkedin.util.degrader.DegraderImpl)11 RequestContext (com.linkedin.r2.message.RequestContext)10 DegraderControl (com.linkedin.util.degrader.DegraderControl)7 URIRequest (com.linkedin.d2.balancer.util.URIRequest)6 CallCompletion (com.linkedin.util.degrader.CallCompletion)6 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)4 PartitionData (com.linkedin.d2.balancer.properties.PartitionData)3 DegraderLoadBalancerStrategyConfig (com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerStrategyConfig)3 RandomHash (com.linkedin.d2.balancer.util.hashing.RandomHash)3 URIRegexHash (com.linkedin.d2.balancer.util.hashing.URIRegexHash)3 LoadBalancerState (com.linkedin.d2.balancer.LoadBalancerState)2 PartitionedLoadBalancerTestState (com.linkedin.d2.balancer.PartitionedLoadBalancerTestState)2 SimpleLoadBalancer (com.linkedin.d2.balancer.simple.SimpleLoadBalancer)2