Search in sources :

Example 21 with DegraderTrackerClient

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

the class DegraderLoadBalancerTest method testAvoidUpdatingStateIfGetRingWithEmptyClients.

/**
 * The test checks the behavior is consistent with getTrackerClient, avoiding to recalculate the state if
 * no clients are passed in, since we also already know that it will be an emtpy Ring
 * This test aims at solving a concurrency problem that would otherwise show up when switching the prioritized
 * scheme from HTTP_ONLY to HTTPS
 */
@Test(groups = { "small", "back-end" })
public void testAvoidUpdatingStateIfGetRingWithEmptyClients() {
    final int PARTITION_ID = 0;
    Map<String, Object> myMap = lbDefaultConfig();
    Long timeInterval = 5000L;
    TestClock clock = new TestClock();
    myMap.put(PropertyKeys.CLOCK, clock);
    DegraderImpl.Config degraderConfig = DegraderConfigFactory.toDegraderConfig(null);
    double qps = 0.3;
    // set up strategy
    List<DegraderTrackerClient> clients = createTrackerClient(10, clock, degraderConfig);
    DegraderLoadBalancerStrategyConfig config = DegraderLoadBalancerStrategyConfig.createHttpConfigFromMap(myMap);
    DegraderLoadBalancerStrategyV3 strategyV3 = new DegraderLoadBalancerStrategyV3(config, "DegraderLoadBalancerTest", null, DEGRADER_STATE_LISTENER_FACTORIES);
    DegraderLoadBalancerStrategyAdapter strategy = new DegraderLoadBalancerStrategyAdapter(strategyV3);
    // get tracker passing some clients
    strategy.getRing(1, PARTITION_ID, toMap(clients));
    String strategyState = strategyV3.getState().getPartition(PARTITION_ID).toString();
    // making some calls to enable the properties to update the strategy
    callClients(10, qps, clients, clock, timeInterval, true, false);
    // make another call that should not trigger update state since no clients are passed, even if we made some
    // calls and the clientGenerationId changed
    Ring<URI> emptyRing = strategy.getRing(2, PARTITION_ID, Collections.emptyMap());
    String strategyStateEmptyClients = strategyV3.getState().getPartition(PARTITION_ID).toString();
    Assert.assertEquals(strategyStateEmptyClients, strategyState, "We should not update the strategy if we pass" + " an empty client list.");
    Assert.assertEquals(emptyRing.getIterator(0).hasNext(), false, "It should return an empty Ring" + " since no clients have been passed");
}
Also used : DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient) DegraderImpl(com.linkedin.util.degrader.DegraderImpl) URI(java.net.URI) AtomicLong(java.util.concurrent.atomic.AtomicLong) Test(org.testng.annotations.Test) DegraderTrackerClientTest(com.linkedin.d2.balancer.clients.DegraderTrackerClientTest)

Example 22 with DegraderTrackerClient

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

the class DegraderLoadBalancerTest method testMediumTrafficHighLatency10Clients.

@Test(groups = { "small", "back-end" })
public void testMediumTrafficHighLatency10Clients() {
    Map<String, Object> myMap = lbDefaultConfig();
    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 = degraderDefaultConfig();
    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 = 6.3;
    // test Strategy V3
    List<DegraderTrackerClient> clients = createTrackerClient(10, clock, degraderConfig);
    DegraderLoadBalancerStrategyConfig config = DegraderLoadBalancerStrategyConfig.createHttpConfigFromMap(myMap);
    DegraderLoadBalancerStrategyV3 strategyV3 = new DegraderLoadBalancerStrategyV3(config, "DegraderLoadBalancerTest", null, DEGRADER_STATE_LISTENER_FACTORIES);
    DegraderLoadBalancerStrategyAdapter strategy = new DegraderLoadBalancerStrategyAdapter(strategyV3);
    testDegraderLoadBalancerSimulator(strategy, clock, timeInterval, clients, qps, degraderConfig);
}
Also used : DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient) DegraderImpl(com.linkedin.util.degrader.DegraderImpl) AtomicLong(java.util.concurrent.atomic.AtomicLong) Test(org.testng.annotations.Test) DegraderTrackerClientTest(com.linkedin.d2.balancer.clients.DegraderTrackerClientTest)

Example 23 with DegraderTrackerClient

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

the class DegraderLoadBalancerTest method testDegraderLoadBalancerStateComparison.

@Test(groups = { "small", "back-end" })
public void testDegraderLoadBalancerStateComparison() throws URISyntaxException {
    long clusterGenerationId = 1;
    long lastUpdated = 29999;
    long currentAverageClusterLatency = 3000;
    Map<String, Object> configMap = new HashMap<>();
    configMap.put(PropertyKeys.HTTP_LB_LOW_WATER_MARK, 500d);
    configMap.put(PropertyKeys.HTTP_LB_STRATEGY_PROPERTIES_POINTS_PER_WEIGHT, 120);
    DegraderLoadBalancerStrategyConfig config = DegraderLoadBalancerStrategyConfig.createHttpConfigFromMap(configMap);
    long clusterCallCount = 15;
    Map<DegraderTrackerClient, LoadBalancerQuarantine> quarantineMap = new HashMap<>();
    Map<DegraderTrackerClient, LoadBalancerQuarantine> quarantineStore = new HashMap<>();
    double currentOverrideDropRate = 0.4;
    boolean initialized = true;
    String name = "degraderV2";
    Map<URI, Integer> points = new HashMap<>();
    Map<DegraderTrackerClient, Double> recoveryMap = new HashMap<>();
    URI uri1 = new URI("http://test.linkedin.com:10010/abc0");
    URI uri2 = new URI("http://test.linkedin.com:10010/abc1");
    URI uri3 = new URI("http://test.linkedin.com:10010/abc2");
    points.put(uri1, 100);
    points.put(uri2, 50);
    points.put(uri3, 120);
    RingFactory<URI> ringFactory = new DelegatingRingFactory<>(config);
    TestClock clock = new TestClock();
    List<DegraderTrackerClient> clients = createTrackerClient(3, clock, null);
    List<DegraderTrackerClientUpdater> clientUpdaters = new ArrayList<>();
    for (DegraderTrackerClient client : clients) {
        recoveryMap.put(client, 0.0);
        clientUpdaters.add(new DegraderTrackerClientUpdater(client, DEFAULT_PARTITION_ID));
    }
    // test DegraderLoadBalancerV3
    points.put(uri1, 100);
    points.put(uri2, 50);
    points.put(uri3, 120);
    PartitionDegraderLoadBalancerState.Strategy strategyV3 = PartitionDegraderLoadBalancerState.Strategy.CALL_DROPPING;
    PartitionDegraderLoadBalancerState oldStateV3 = new PartitionDegraderLoadBalancerState(clusterGenerationId, lastUpdated, initialized, ringFactory, points, strategyV3, currentOverrideDropRate, currentAverageClusterLatency, recoveryMap, name, null, clusterCallCount, 0, 0, quarantineMap, quarantineStore, null, 0);
    PartitionDegraderLoadBalancerState newStateV3 = new PartitionDegraderLoadBalancerState(clusterGenerationId, lastUpdated, initialized, ringFactory, points, strategyV3, currentOverrideDropRate, currentAverageClusterLatency, recoveryMap, name, null, clusterCallCount, 0, 0, quarantineMap, quarantineStore, null, 0);
    assertTrue(DegraderLoadBalancerStrategyV3.isOldStateTheSameAsNewState(oldStateV3, newStateV3));
    newStateV3 = new PartitionDegraderLoadBalancerState(clusterGenerationId + 1, lastUpdated, initialized, ringFactory, points, strategyV3, currentOverrideDropRate, currentAverageClusterLatency, recoveryMap, name, null, clusterCallCount, 0, 0, quarantineMap, quarantineStore, null, 0);
    assertTrue(DegraderLoadBalancerStrategyV3.isOldStateTheSameAsNewState(oldStateV3, newStateV3));
    newStateV3 = new PartitionDegraderLoadBalancerState(clusterGenerationId, lastUpdated + 300, initialized, ringFactory, points, strategyV3, currentOverrideDropRate, currentAverageClusterLatency, recoveryMap, name, null, clusterCallCount, 0, 0, quarantineMap, quarantineStore, null, 0);
    assertTrue(DegraderLoadBalancerStrategyV3.isOldStateTheSameAsNewState(oldStateV3, newStateV3));
    points.put(uri2, 77);
    newStateV3 = new PartitionDegraderLoadBalancerState(clusterGenerationId, lastUpdated, initialized, ringFactory, points, strategyV3, currentOverrideDropRate, currentAverageClusterLatency, recoveryMap, name, null, clusterCallCount, 0, 0, quarantineMap, quarantineStore, null, 0);
    assertFalse(DegraderLoadBalancerStrategyV3.isOldStateTheSameAsNewState(oldStateV3, newStateV3));
    points.put(uri2, 50);
    newStateV3 = new PartitionDegraderLoadBalancerState(clusterGenerationId, lastUpdated, initialized, ringFactory, points, strategyV3, currentOverrideDropRate + 0.4, currentAverageClusterLatency, recoveryMap, name, null, clusterCallCount, 0, 0, quarantineMap, quarantineStore, null, 0);
    assertFalse(DegraderLoadBalancerStrategyV3.isOldStateTheSameAsNewState(oldStateV3, newStateV3));
    newStateV3 = new PartitionDegraderLoadBalancerState(clusterGenerationId, lastUpdated, initialized, ringFactory, points, strategyV3, currentOverrideDropRate, currentAverageClusterLatency + 55, recoveryMap, name, null, clusterCallCount, 0, 0, quarantineMap, quarantineStore, null, 0);
    // we don't care about averageClusterLatency for comparing states
    assertTrue(DegraderLoadBalancerStrategyV3.isOldStateTheSameAsNewState(oldStateV3, newStateV3));
    for (DegraderTrackerClient client : clients) {
        recoveryMap.put(client, 0.5);
    }
    newStateV3 = new PartitionDegraderLoadBalancerState(clusterGenerationId, lastUpdated, initialized, ringFactory, points, strategyV3, currentOverrideDropRate, currentAverageClusterLatency, recoveryMap, name, null, clusterCallCount, 0, 0, quarantineMap, quarantineStore, null, 0);
    assertFalse(DegraderLoadBalancerStrategyV3.isOldStateTheSameAsNewState(oldStateV3, newStateV3));
    // test state health comparison
    assertFalse(DegraderLoadBalancerStrategyV3.isNewStateHealthy(newStateV3, config, clientUpdaters, DEFAULT_PARTITION_ID));
    // make cluster average latency to be 300 to be lower than lowWaterMark but still not healthy because
    // points map has clients with less than perfect health
    newStateV3 = new PartitionDegraderLoadBalancerState(clusterGenerationId, lastUpdated, initialized, ringFactory, points, strategyV3, currentOverrideDropRate, 300, recoveryMap, name, null, clusterCallCount, 0, 0, quarantineMap, quarantineStore, null, 0);
    assertFalse(DegraderLoadBalancerStrategyV3.isNewStateHealthy(newStateV3, config, clientUpdaters, DEFAULT_PARTITION_ID));
    // make all points to have 120 so the cluster becomes "healthy"
    points.put(uri1, 120);
    points.put(uri2, 120);
    points.put(uri3, 120);
    newStateV3 = new PartitionDegraderLoadBalancerState(clusterGenerationId, lastUpdated, initialized, ringFactory, points, strategyV3, currentOverrideDropRate, 300, recoveryMap, name, null, clusterCallCount, 0, 0, quarantineMap, quarantineStore, null, 0);
    assertTrue(DegraderLoadBalancerStrategyV3.isNewStateHealthy(newStateV3, config, clientUpdaters, DEFAULT_PARTITION_ID));
    // if currentAverageClusterLatency is > low water mark then cluster becomes unhealthy
    newStateV3 = new PartitionDegraderLoadBalancerState(clusterGenerationId, lastUpdated, initialized, ringFactory, points, strategyV3, currentOverrideDropRate, currentAverageClusterLatency, recoveryMap, name, null, clusterCallCount, 0, 0, quarantineMap, quarantineStore, null, 0);
    assertFalse(DegraderLoadBalancerStrategyV3.isNewStateHealthy(newStateV3, config, clientUpdaters, DEFAULT_PARTITION_ID));
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) URI(java.net.URI) DelegatingRingFactory(com.linkedin.d2.balancer.strategies.DelegatingRingFactory) LoadBalancerQuarantine(com.linkedin.d2.balancer.strategies.LoadBalancerQuarantine) DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient) Test(org.testng.annotations.Test) DegraderTrackerClientTest(com.linkedin.d2.balancer.clients.DegraderTrackerClientTest)

Example 24 with DegraderTrackerClient

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

the class DegraderLoadBalancerTest method testLowTrafficHighLatency1Client.

@Test(groups = { "small", "back-end" })
public void testLowTrafficHighLatency1Client() {
    Map<String, Object> myMap = lbDefaultConfig();
    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_CLUSTER_MIN_CALL_COUNT_HIGH_WATER_MARK, 1l);
    myMap.put(PropertyKeys.HTTP_LB_CLUSTER_MIN_CALL_COUNT_LOW_WATER_MARK, 1l);
    // we need to override the min call count to 0 because we're testing a service with low traffic.
    // if we don't do this, the computedDropRate will not change and we will never be able to recover
    // after we degraded the cluster.
    Map<String, String> degraderImplProperties = degraderDefaultConfig();
    degraderImplProperties.put(PropertyKeys.DEGRADER_MIN_CALL_COUNT, "1");
    degraderImplProperties.put(PropertyKeys.DEGRADER_HIGH_ERROR_RATE, "0.5");
    degraderImplProperties.put(PropertyKeys.DEGRADER_LOW_ERROR_RATE, "0.2");
    DegraderImpl.Config degraderConfig = DegraderConfigFactory.toDegraderConfig(degraderImplProperties);
    double qps = 0.3;
    // test Strategy V3
    List<DegraderTrackerClient> clients = createTrackerClient(1, clock, degraderConfig);
    DegraderLoadBalancerStrategyConfig config = DegraderLoadBalancerStrategyConfig.createHttpConfigFromMap(myMap);
    DegraderLoadBalancerStrategyV3 strategyV3 = new DegraderLoadBalancerStrategyV3(config, "DegraderLoadBalancerTest", null, DEGRADER_STATE_LISTENER_FACTORIES);
    DegraderLoadBalancerStrategyAdapter strategy = new DegraderLoadBalancerStrategyAdapter(strategyV3);
    testDegraderLoadBalancerSimulator(strategy, clock, timeInterval, clients, qps, degraderConfig);
}
Also used : DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient) DegraderImpl(com.linkedin.util.degrader.DegraderImpl) AtomicLong(java.util.concurrent.atomic.AtomicLong) Test(org.testng.annotations.Test) DegraderTrackerClientTest(com.linkedin.d2.balancer.clients.DegraderTrackerClientTest)

Example 25 with DegraderTrackerClient

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

the class DegraderLoadBalancerTest method testLowTrafficHighLatency10Clients.

@Test(groups = { "small", "back-end" })
public void testLowTrafficHighLatency10Clients() {
    Map<String, Object> myMap = lbDefaultConfig();
    Long timeInterval = 5000L;
    TestClock clock = new TestClock();
    myMap.put(PropertyKeys.CLOCK, clock);
    myMap.put(PropertyKeys.HTTP_LB_STRATEGY_PROPERTIES_UPDATE_INTERVAL_MS, timeInterval);
    // we need to override the min call count to 0 because we're testing a service with low traffic.
    // if we don't do this, the computedDropRate will not change and we will never be able to recover
    // after we degraded the cluster.
    Map<String, String> degraderImplProperties = degraderDefaultConfig();
    degraderImplProperties.put(PropertyKeys.DEGRADER_MIN_CALL_COUNT, "1");
    degraderImplProperties.put(PropertyKeys.DEGRADER_HIGH_ERROR_RATE, "0.5");
    degraderImplProperties.put(PropertyKeys.DEGRADER_LOW_ERROR_RATE, "0.2");
    DegraderImpl.Config degraderConfig = DegraderConfigFactory.toDegraderConfig(degraderImplProperties);
    double qps = 0.3;
    // test Strategy V3
    List<DegraderTrackerClient> clients = createTrackerClient(10, clock, degraderConfig);
    DegraderLoadBalancerStrategyConfig config = DegraderLoadBalancerStrategyConfig.createHttpConfigFromMap(myMap);
    DegraderLoadBalancerStrategyV3 strategyV3 = new DegraderLoadBalancerStrategyV3(config, "DegraderLoadBalancerTest", null, DEGRADER_STATE_LISTENER_FACTORIES);
    DegraderLoadBalancerStrategyAdapter strategy = new DegraderLoadBalancerStrategyAdapter(strategyV3);
    testDegraderLoadBalancerSimulator(strategy, clock, timeInterval, clients, qps, degraderConfig);
}
Also used : DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient) DegraderImpl(com.linkedin.util.degrader.DegraderImpl) AtomicLong(java.util.concurrent.atomic.AtomicLong) 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