Search in sources :

Example 56 with DegraderLoadBalancerStrategyConfig

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

the class DegraderLoadBalancerTest method testStateIsNullAndCallCountIsGreaterThanZero.

@Test(groups = { "small", "back-end" })
public void testStateIsNullAndCallCountIsGreaterThanZero() 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, DEGRADER_STATE_LISTENER_FACTORIES);
    List<DegraderTrackerClient> clients = new ArrayList<>();
    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) with an override
    // of 0d
    getTrackerClient(strategy, null, new RequestContext(), -1, clients);
    for (DegraderTrackerClient client : clients) {
        assertEquals(client.getDegraderControl(DEFAULT_PARTITION_ID).getOverrideDropRate(), 0d);
    }
}
Also used : 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)

Example 57 with DegraderLoadBalancerStrategyConfig

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

the class DelegatingRingFactoryTest method testRandomChangePoints.

@Test(groups = { "small", "back-end" })
public void testRandomChangePoints() throws URISyntaxException {
    int pointNum = 5;
    int loopNum = 100;
    Map<String, Integer> pointsMp = buildPointsMap(pointNum);
    Map<String, Integer> maxPoints = new HashMap<>(pointNum);
    Random random = new Random();
    for (String uri : pointsMp.keySet()) {
        maxPoints.put(uri, 100);
    }
    PointBasedConsistentHashRingFactory<String> ringFactory = new PointBasedConsistentHashRingFactory<>(new DegraderLoadBalancerStrategyConfig(1L));
    Ring<String> ring = ringFactory.createRing(pointsMp);
    assertNotNull(ring.get(1000));
    for (int i = 0; i < loopNum; ++i) {
        // new point list
        for (String uri : pointsMp.keySet()) {
            int newPoints = random.nextInt(200);
            if (newPoints == 0) {
                continue;
            }
            pointsMp.put(uri, newPoints);
            if (newPoints > maxPoints.get(uri)) {
                maxPoints.put(uri, ((newPoints + 3) / 4) * 4);
            }
        }
        ring = ringFactory.createRing(pointsMp);
        assertNotNull(ring.get(1000));
        Map<String, List<Point<String>>> pointList = ringFactory.getPointsMap();
        for (String uri : pointsMp.keySet()) {
            assertEquals((int) maxPoints.get(uri), pointList.get(uri).size());
        }
    }
}
Also used : Random(java.util.Random) HashMap(java.util.HashMap) DegraderLoadBalancerStrategyConfig(com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerStrategyConfig) List(java.util.List) Point(com.linkedin.d2.balancer.util.hashing.ConsistentHashRing.Point) Test(org.testng.annotations.Test)

Example 58 with DegraderLoadBalancerStrategyConfig

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

the class DegraderLoadBalancerStrategyV3 method enrollNewClientInRecoveryMap.

/**
 *   /**
 * Enroll new client into RecoveryMap
 *
 * When fastRecovery mode is enabled, we want to enroll the new client into recoveryMap to help its recovery
 */
private static void enrollNewClientInRecoveryMap(Map<DegraderTrackerClient, Double> recoveryMap, PartitionDegraderLoadBalancerState state, DegraderLoadBalancerStrategyConfig config, DegraderControl degraderControl, DegraderTrackerClientUpdater clientUpdater) {
    DegraderTrackerClient client = clientUpdater.getTrackerClient();
    if (// client is not in the map yet
    !recoveryMap.containsKey(client) && // client is new
    !state.getTrackerClients().contains(client) && // Fast recovery is enabled
    config.getRingRampFactor() > FAST_RECOVERY_THRESHOLD && // Slow start is enabled
    degraderControl.getInitialDropRate() > SLOW_START_THRESHOLD && // current client is not degrading or QPS is too low
    !degraderControl.isHigh() && // doNotSlowStart is set to false
    !client.doNotSlowStart()) {
        recoveryMap.put(client, clientUpdater.getMaxDropRate());
        // also set the maxDropRate to the computedDropRate if not 1;
        double maxDropRate = 1.0 - config.getInitialRecoveryLevel();
        clientUpdater.setMaxDropRate(Math.min(degraderControl.getCurrentComputedDropRate(), maxDropRate));
    }
}
Also used : DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient)

Example 59 with DegraderLoadBalancerStrategyConfig

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

the class DegraderLoadBalancerStrategyV3 method getUnhealthyTrackerClients.

private static List<DegraderTrackerClient> getUnhealthyTrackerClients(List<DegraderTrackerClientUpdater> degraderTrackerClientUpdaters, Map<URI, Integer> pointsMap, Map<DegraderTrackerClient, LoadBalancerQuarantine> quarantineMap, DegraderLoadBalancerStrategyConfig config, int partitionId) {
    List<DegraderTrackerClient> unhealthyClients = new ArrayList<>();
    for (DegraderTrackerClientUpdater clientUpdater : degraderTrackerClientUpdaters) {
        DegraderTrackerClient client = clientUpdater.getTrackerClient();
        int perfectHealth = (int) (client.getPartitionWeight(partitionId) * client.getSubsetWeight(partitionId) * config.getPointsPerWeight());
        URI uri = client.getUri();
        if (!pointsMap.containsKey(uri)) {
            _log.warn("Client with URI {} is absent in point map, pointMap={}, quarantineMap={}", new Object[] { uri, pointsMap, quarantineMap });
            continue;
        }
        Integer point = pointsMap.get(uri);
        if (point < perfectHealth) {
            unhealthyClients.add(client);
        }
    }
    return unhealthyClients;
}
Also used : DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient) ArrayList(java.util.ArrayList) URI(java.net.URI)

Example 60 with DegraderLoadBalancerStrategyConfig

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

the class DegraderLoadBalancerStrategyV3 method checkQuarantineState.

/**
 * checkQuarantineState decides if the D2Quarantine can be enabled or not, by health
 * checking all the trackerClients once. It enables quarantine only if at least one of the
 * clients return success for the checking.
 *
 * The reasons for this checking include:
 *
 * . The default method "OPTIONS" is not always enabled by the service
 * . The user can config any path/method for checking. We do a sanity checking to
 *   make sure the configuration is correct, and service/host responds in time.
 *   Otherwise the host can be kept in quarantine forever if we blindly enable it.
 *
 * This check actually can warm up the R2 connection pool by making a connection to
 * each trackerClient. However since the check happens before any real requests are sent,
 * it generally takes much longer time to get the results, due to different warming up
 * requirements. Therefore the checking will be retried in next update if current check
 * fails.
 *
 * This function is supposed to be protected by the update lock.
 *
 * @param clients
 * @param config
 */
private void checkQuarantineState(List<DegraderTrackerClientUpdater> clients, DegraderLoadBalancerStrategyConfig config) {
    Callback<None> healthCheckCallback = new Callback<None>() {

        @Override
        public void onError(Throwable e) {
            // Do nothing as the quarantine is disabled by default
            if (!_state.isQuarantineEnabled()) {
                // No need to log the error message if quarantine is already enabled
                _rateLimitedLogger.warn("Error enabling quarantine. Health checking failed for service {}: ", _state.getServiceName(), e);
            }
        }

        @Override
        public void onSuccess(None result) {
            if (_state.tryEnableQuarantine()) {
                _log.info("Quarantine is enabled for service {}", _state.getServiceName());
            }
        }
    };
    // Ideally we would like to healthchecking all the service hosts (ie all TrackerClients) because
    // this can help to warm up the R2 connections to the service hosts, thus speed up the initial access
    // speed when d2client starts to access those hosts. However this can expose/expedite the problem that
    // the d2client host needs too many connections or file handles to all the hosts, when the downstream
    // services have large amount of hosts. Before that problem is addressed, we limit the number of hosts
    // for pre-healthchecking to a small number
    clients.stream().limit(MAX_HOSTS_TO_CHECK_QUARANTINE).forEach(client -> {
        try {
            HealthCheck healthCheckClient = _state.getHealthCheckMap().get(client);
            if (healthCheckClient == null) {
                // create a new client if not exits
                healthCheckClient = new HealthCheckClientBuilder().setHealthCheckOperations(config.getHealthCheckOperations()).setHealthCheckPath(config.getHealthCheckPath()).setServicePath(config.getServicePath()).setClock(config.getClock()).setLatency(config.getQuarantineLatency()).setMethod(config.getHealthCheckMethod()).setClient(client.getTrackerClient()).build();
                _state.putHealthCheckClient(client, healthCheckClient);
            }
            healthCheckClient.checkHealth(healthCheckCallback);
        } catch (URISyntaxException e) {
            _log.error("Error to build healthCheckClient ", e);
        }
    });
    // also remove the entries that the corresponding trackerClientUpdaters do not exist anymore
    for (DegraderTrackerClientUpdater client : _state.getHealthCheckMap().keySet()) {
        if (!clients.contains(client)) {
            _state.getHealthCheckMap().remove(client);
        }
    }
}
Also used : Callback(com.linkedin.common.callback.Callback) HealthCheck(com.linkedin.d2.balancer.util.healthcheck.HealthCheck) HealthCheckClientBuilder(com.linkedin.d2.balancer.util.healthcheck.HealthCheckClientBuilder) URISyntaxException(java.net.URISyntaxException) None(com.linkedin.common.util.None)

Aggregations

Test (org.testng.annotations.Test)35 DegraderTrackerClient (com.linkedin.d2.balancer.clients.DegraderTrackerClient)31 DegraderTrackerClientTest (com.linkedin.d2.balancer.clients.DegraderTrackerClientTest)28 ArrayList (java.util.ArrayList)26 URI (java.net.URI)22 AtomicLong (java.util.concurrent.atomic.AtomicLong)21 TrackerClient (com.linkedin.d2.balancer.clients.TrackerClient)19 HashMap (java.util.HashMap)16 DegraderImpl (com.linkedin.util.degrader.DegraderImpl)13 RequestContext (com.linkedin.r2.message.RequestContext)12 DegraderControl (com.linkedin.util.degrader.DegraderControl)9 DegraderLoadBalancerStrategyConfig (com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerStrategyConfig)8 URIRequest (com.linkedin.d2.balancer.util.URIRequest)7 CallCompletion (com.linkedin.util.degrader.CallCompletion)7 DegraderTrackerClientImpl (com.linkedin.d2.balancer.clients.DegraderTrackerClientImpl)5 DelegatingRingFactory (com.linkedin.d2.balancer.strategies.DelegatingRingFactory)5 LoadBalancerQuarantine (com.linkedin.d2.balancer.strategies.LoadBalancerQuarantine)5 List (java.util.List)4 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)4 LoadBalancerState (com.linkedin.d2.balancer.LoadBalancerState)3