Search in sources :

Example 11 with DegraderTrackerClientImpl

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

the class DegraderLoadBalancerTest method testHighLowWatermarks.

@Test(groups = { "small", "back-end" })
public void testHighLowWatermarks() {
    final int NUM_CHECKS = 5;
    Map<String, Object> myMap = lbDefaultConfig();
    Long timeInterval = 5000L;
    double globalStepUp = 0.4;
    double globalStepDown = 0.4;
    double highWaterMark = 1000;
    double lowWaterMark = 50;
    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_GLOBAL_STEP_UP, globalStepUp);
    myMap.put(PropertyKeys.HTTP_LB_GLOBAL_STEP_DOWN, globalStepDown);
    myMap.put(PropertyKeys.HTTP_LB_HIGH_WATER_MARK, highWaterMark);
    myMap.put(PropertyKeys.HTTP_LB_LOW_WATER_MARK, lowWaterMark);
    myMap.put(PropertyKeys.HTTP_LB_CLUSTER_MIN_CALL_COUNT_HIGH_WATER_MARK, 1l);
    myMap.put(PropertyKeys.HTTP_LB_CLUSTER_MIN_CALL_COUNT_LOW_WATER_MARK, 1l);
    DegraderLoadBalancerStrategyConfig config = DegraderLoadBalancerStrategyConfig.createHttpConfigFromMap(myMap);
    DegraderLoadBalancerStrategyV3 strategy = new DegraderLoadBalancerStrategyV3(config, "DegraderLoadBalancerTest", null, DEGRADER_STATE_LISTENER_FACTORIES);
    List<DegraderTrackerClient> clients = new ArrayList<>();
    URI uri1 = URI.create("http://test.linkedin.com:3242/fdsaf");
    URIRequest request = new URIRequest(uri1);
    DegraderTrackerClient client1 = new DegraderTrackerClientImpl(uri1, getDefaultPartitionData(1d), new TestLoadBalancerClient(uri1), clock, null);
    clients.add(client1);
    DegraderControl dcClient1Default = client1.getDegraderControl(DEFAULT_PARTITION_ID);
    dcClient1Default.setOverrideMinCallCount(5);
    dcClient1Default.setMinCallCount(5);
    List<CallCompletion> ccList = new ArrayList<>();
    CallCompletion cc;
    TrackerClient resultTC = getTrackerClient(strategy, request, new RequestContext(), 1, clients);
    // The override drop rate should be zero at this point.
    assertEquals(dcClient1Default.getOverrideDropRate(), 0.0);
    // make high latency calls to the tracker client, verify the override drop rate doesn't change
    for (int j = 0; j < NUM_CHECKS; j++) {
        cc = client1.getCallTracker().startCall();
        ccList.add(cc);
    }
    clock.addMs((long) highWaterMark);
    for (Iterator<CallCompletion> iter = ccList.listIterator(); iter.hasNext(); ) {
        cc = iter.next();
        cc.endCall();
        iter.remove();
    }
    // go to next time interval.
    clock.addMs(timeInterval);
    // try call dropping on the next updateState
    strategy.setStrategy(DEFAULT_PARTITION_ID, PartitionDegraderLoadBalancerState.Strategy.CALL_DROPPING);
    resultTC = getTrackerClient(strategy, request, new RequestContext(), 1, clients);
    // we now expect that the override drop rate stepped up because updateState
    // made that decision.
    assertEquals(dcClient1Default.getOverrideDropRate(), globalStepUp);
    // make mid latency calls to the tracker client, verify the override drop rate doesn't change
    for (int j = 0; j < NUM_CHECKS; j++) {
        // need to use client1 because the resultTC may be null
        cc = client1.getCallTracker().startCall();
        ccList.add(cc);
    }
    clock.addMs((long) highWaterMark - 1);
    for (Iterator<CallCompletion> iter = ccList.listIterator(); iter.hasNext(); ) {
        cc = iter.next();
        cc.endCall();
        iter.remove();
    }
    // go to next time interval.
    clock.addMs(timeInterval);
    double previousOverrideDropRate = dcClient1Default.getOverrideDropRate();
    // try call dropping on the next updateState
    strategy.setStrategy(DEFAULT_PARTITION_ID, PartitionDegraderLoadBalancerState.Strategy.CALL_DROPPING);
    resultTC = getTrackerClient(strategy, request, new RequestContext(), 1, clients);
    assertEquals(dcClient1Default.getOverrideDropRate(), previousOverrideDropRate);
    // make low latency calls to the tracker client, verify the override drop rate decreases
    for (int j = 0; j < NUM_CHECKS; j++) {
        cc = client1.getCallTracker().startCall();
        ccList.add(cc);
    }
    clock.addMs((long) lowWaterMark);
    for (Iterator<CallCompletion> iter = ccList.listIterator(); iter.hasNext(); ) {
        cc = iter.next();
        cc.endCall();
        iter.remove();
    }
    // go to next time interval.
    clock.addMs(timeInterval);
    // try Call dropping on this updateState
    strategy.setStrategy(DEFAULT_PARTITION_ID, PartitionDegraderLoadBalancerState.Strategy.CALL_DROPPING);
    resultTC = getTrackerClient(strategy, request, new RequestContext(), 1, clients);
    assertEquals(((DegraderTrackerClient) resultTC).getDegraderControl(DEFAULT_PARTITION_ID).getOverrideDropRate(), 0.0);
}
Also used : DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient) ArrayList(java.util.ArrayList) URIRequest(com.linkedin.d2.balancer.util.URIRequest) 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) AtomicLong(java.util.concurrent.atomic.AtomicLong) 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 12 with DegraderTrackerClientImpl

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

the class LoadBalancerStrategyBenchmark method createDegraderTrackerClients.

private static Map<URI, TrackerClient> createDegraderTrackerClients(int numHosts) {
    Map<URI, TrackerClient> trackerClients = new HashMap<>();
    for (int i = 0; i < numHosts; i++) {
        URI uri = URI.create(URI_PREFIX + i + URI_SUFFIX);
        trackerClients.put(uri, new DegraderTrackerClientImpl(uri, DEFAULT_PARTITION_DATA_MAP, new BaseTransportTestClient(), CLOCK, null));
    }
    return trackerClients;
}
Also used : TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) HashMap(java.util.HashMap) DegraderTrackerClientImpl(com.linkedin.d2.balancer.clients.DegraderTrackerClientImpl) URI(java.net.URI)

Example 13 with DegraderTrackerClientImpl

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

the class DegraderLoadBalancerTest method TestRandomIncreaseReduceTrackerClients.

@Test(groups = { "small", "back-end" }, dataProvider = "consistentHashAlgorithms")
public void TestRandomIncreaseReduceTrackerClients(String consistentHashAlgorithm) {
    final DegraderLoadBalancerStrategyV3 strategy = getStrategy(consistentHashAlgorithm);
    TestClock testClock = new TestClock();
    String baseUri = "http://linkedin.com:9999";
    int numberOfClients = 100;
    int loopNumber = 100;
    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);
    Random random = new Random();
    final List<DegraderTrackerClient> clients = new ArrayList<>();
    random.setSeed(123456789L);
    for (int i = 0; i < loopNumber; ++i) {
        int currentSize = clients.size();
        if (currentSize > numberOfClients) {
            // need to remove some clients
            clients.subList(numberOfClients, currentSize).clear();
        } else {
            // add more clients
            for (int j = currentSize; j < numberOfClients; j++) {
                URI uri = URI.create(baseUri + j);
                DegraderTrackerClient client = new DegraderTrackerClientImpl(uri, getDefaultPartitionData(1, 1), new TestLoadBalancerClient(uri), testClock, degraderConfig);
                clients.add(client);
            }
        }
        TrackerClient client = strategy.getTrackerClient(null, new RequestContext(), i, DefaultPartitionAccessor.DEFAULT_PARTITION_ID, toMap(clients));
        assertNotNull(client);
        // update the client number
        if (random.nextBoolean()) {
            numberOfClients += random.nextInt(numberOfClients / 5);
        } else {
            numberOfClients -= random.nextInt(numberOfClients / 5);
        }
    }
}
Also used : HashMap(java.util.HashMap) DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient) DegraderImpl(com.linkedin.util.degrader.DegraderImpl) ArrayList(java.util.ArrayList) URI(java.net.URI) Random(java.util.Random) 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 14 with DegraderTrackerClientImpl

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

the class DegraderLoadBalancerTest method clusterTotalRecovery1TC.

/**
 * simulates the situation where a cluster latency gets so high that we will reduce the number of
 * points in hashring to 0 and then increase the call drop rate to 1.0
 * This will causes the cluster to receive no traffic and we want to see if the cluster can recover
 * from such situation.
 * @param myMap
 * @param clock
 * @param timeInterval
 * @param strategy
 */
public void clusterTotalRecovery1TC(Map<String, Object> myMap, TestClock clock, Long timeInterval, DegraderLoadBalancerStrategyAdapter strategy) {
    final int NUM_CHECKS = 5;
    final Long TIME_INTERVAL = timeInterval;
    DegraderLoadBalancerStrategyConfig config = DegraderLoadBalancerStrategyConfig.createHttpConfigFromMap(myMap);
    List<DegraderTrackerClient> clients = new ArrayList<>();
    URI uri1 = URI.create("http://test.linkedin.com:3242/fdsaf");
    URIRequest request = new URIRequest(uri1);
    DegraderTrackerClient client1 = new DegraderTrackerClientImpl(uri1, getDefaultPartitionData(1d), new TestLoadBalancerClient(uri1), clock, null);
    clients.add(client1);
    // force client1 to be disabled
    DegraderControl dcClient1Default = client1.getDegraderControl(DEFAULT_PARTITION_ID);
    dcClient1Default.setOverrideMinCallCount(5);
    dcClient1Default.setMinCallCount(5);
    dcClient1Default.setMaxDropRate(1d);
    dcClient1Default.setUpStep(1.0d);
    List<CallCompletion> ccList = new ArrayList<>();
    CallCompletion cc;
    for (int j = 0; j < NUM_CHECKS; j++) {
        cc = client1.getCallTracker().startCall();
        ccList.add(cc);
    }
    // add high latency and errors to shut off traffic to this tracker client.
    clock.addMs(3500);
    for (Iterator<CallCompletion> iter = ccList.listIterator(); iter.hasNext(); ) {
        cc = iter.next();
        cc.endCallWithError();
        iter.remove();
    }
    // go to next time interval.
    clock.addMs(TIME_INTERVAL);
    Assert.assertEquals(dcClient1Default.getCurrentComputedDropRate(), 1.0);
    // trigger a state update
    TrackerClient resultTC = getTrackerClient(strategy, request, new RequestContext(), 1, clients);
    // now we mimic the high latency and force the state to drop all calls so to make
    // the overrideClusterDropRate to 1.0
    ccList = new ArrayList<>();
    for (int j = 0; j < NUM_CHECKS; j++) {
        cc = client1.getCallTracker().startCall();
        ccList.add(cc);
    }
    // make sure that the latency is really high
    clock.addMs(3500);
    for (Iterator<CallCompletion> iter = ccList.listIterator(); iter.hasNext(); ) {
        cc = iter.next();
        cc.endCallWithError();
        iter.remove();
    }
    // go to next time interval.
    clock.addMs(TIME_INTERVAL);
    // trigger a state update
    resultTC = getTrackerClient(strategy, request, new RequestContext(), 1, clients);
    // this time the cluster override drop rate is set to 1.0 so resultTC should be null because we drop the client
    assertNull(resultTC);
    assertEquals(strategy.getCurrentOverrideDropRate(), config.getGlobalStepUp());
    // add another time interval
    clock.addMs(TIME_INTERVAL);
    // usually we alternate between LoadBalancing and CallDropping strategy but we want to test
    // call dropping strategy
    strategy.setStrategyToCallDrop();
    // we simulate call drop by not calling callCompletion endCall() or endCallWithEror() like we did above
    // because override drop rate is set to 1.0 that means all call will be dropped so resultTc should be null
    resultTC = getTrackerClient(strategy, request, new RequestContext(), 1, clients);
    // this time the cluster override drop rate is set to 0.2 because we're recovering
    assertEquals(strategy.getCurrentOverrideDropRate(), 1 - config.getGlobalStepDown());
    // add another time interval
    clock.addMs(TIME_INTERVAL);
    // set the strategy to callDropping again
    strategy.setStrategyToCallDrop();
    // because override drop rate is set to 0.2 and we simulate as if we still don't get any call
    // this cycle we will set the override drop rate to 0
    resultTC = getTrackerClient(strategy, request, new RequestContext(), 1, clients);
    assertEquals(strategy.getCurrentOverrideDropRate(), 0.0);
}
Also used : DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient) ArrayList(java.util.ArrayList) URIRequest(com.linkedin.d2.balancer.util.URIRequest) 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) AtomicLong(java.util.concurrent.atomic.AtomicLong) DegraderTrackerClientImpl(com.linkedin.d2.balancer.clients.DegraderTrackerClientImpl) RequestContext(com.linkedin.r2.message.RequestContext)

Example 15 with DegraderTrackerClientImpl

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

the class DegraderLoadBalancerTest method testOneTrackerClientForPartition.

@Test(groups = { "small", "back-end" })
public void testOneTrackerClientForPartition() throws URISyntaxException {
    DegraderLoadBalancerStrategyV3 strategy = getStrategy();
    Map<URI, TrackerClient> clients = new HashMap<>();
    URI uri1 = URI.create("http://test.linkedin.com:3242/fdsaf");
    Map<Integer, PartitionData> weightMap = new HashMap<>();
    weightMap.put(0, new PartitionData(1d));
    TrackerClient client = new DegraderTrackerClientImpl(uri1, weightMap, new TestLoadBalancerClient(uri1), new TestClock(), null);
    clients.put(client.getUri(), client);
    // should always get the only client in the list
    for (int i = 0; i < 1000; ++i) {
        assertEquals(strategy.getTrackerClient(null, new RequestContext(), 0, 0, clients), client);
    }
}
Also used : HashMap(java.util.HashMap) URI(java.net.URI) DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient) TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) PartitionData(com.linkedin.d2.balancer.properties.PartitionData) 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)

Aggregations

URI (java.net.URI)20 DegraderTrackerClientImpl (com.linkedin.d2.balancer.clients.DegraderTrackerClientImpl)19 TrackerClient (com.linkedin.d2.balancer.clients.TrackerClient)15 RequestContext (com.linkedin.r2.message.RequestContext)15 Test (org.testng.annotations.Test)15 DegraderTrackerClient (com.linkedin.d2.balancer.clients.DegraderTrackerClient)14 HashMap (java.util.HashMap)13 ArrayList (java.util.ArrayList)12 PartitionData (com.linkedin.d2.balancer.properties.PartitionData)11 DegraderTrackerClientTest (com.linkedin.d2.balancer.clients.DegraderTrackerClientTest)10 DegraderControl (com.linkedin.util.degrader.DegraderControl)9 CallCompletion (com.linkedin.util.degrader.CallCompletion)7 URIRequest (com.linkedin.d2.balancer.util.URIRequest)5 DegraderImpl (com.linkedin.util.degrader.DegraderImpl)5 AtomicLong (java.util.concurrent.atomic.AtomicLong)5 SettableClock (com.linkedin.util.clock.SettableClock)4 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)4 ByteString (com.linkedin.data.ByteString)3 RestRequest (com.linkedin.r2.message.rest.RestRequest)3 ServiceProperties (com.linkedin.d2.balancer.properties.ServiceProperties)2