Search in sources :

Example 1 with DegraderTrackerClient

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

the class DegraderLoadBalancerStrategyV3 method overrideMinCallCount.

/**
 * Both the drop in hash ring points and the global drop rate influence the minimum call count
 * that we should see to qualify for a state update. Currently, both factors are equally weighed,
 * and multiplied together to come up with a scale factor. With this scheme, if either factor is
 * zero, then the overrideMinCallCount will be set to 1. If both factors are at half weight, then
 * the overall weight will be .5 * .5 = .25 of the original minCallCount.
 *
 * @param newOverrideDropRate
 * @param degraderTrackerClientUpdaters
 * @param pointsMap
 * @param pointsPerWeight
 */
public static void overrideMinCallCount(int partitionId, double newOverrideDropRate, List<DegraderTrackerClientUpdater> degraderTrackerClientUpdaters, Map<URI, Integer> pointsMap, int pointsPerWeight) {
    for (DegraderTrackerClientUpdater clientUpdater : degraderTrackerClientUpdaters) {
        if (!pointsMap.containsKey(clientUpdater.getTrackerClient().getUri())) {
            continue;
        }
        DegraderTrackerClient client = clientUpdater.getTrackerClient();
        DegraderControl degraderControl = client.getDegraderControl(partitionId);
        int currentOverrideMinCallCount = client.getDegraderControl(partitionId).getOverrideMinCallCount();
        double hashFactor = pointsMap.get(client.getUri()) / pointsPerWeight;
        double transmitFactor = 1.0 - newOverrideDropRate;
        int newOverrideMinCallCount = (int) Math.max(Math.round(degraderControl.getMinCallCount() * hashFactor * transmitFactor), 1);
        if (newOverrideMinCallCount != currentOverrideMinCallCount) {
            clientUpdater.setOverrideMinCallCount(newOverrideMinCallCount);
            // log min call count change if current value != initial value
            if (currentOverrideMinCallCount != DegraderImpl.DEFAULT_OVERRIDE_MIN_CALL_COUNT) {
                warn(_log, "partitionId=", partitionId, "overriding Min Call Count to ", newOverrideMinCallCount, " for client: ", client.getUri());
            }
        }
    }
}
Also used : DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient) DegraderControl(com.linkedin.util.degrader.DegraderControl)

Example 2 with DegraderTrackerClient

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

the class DegraderLoadBalancerStrategyV3 method updatePartitionState.

private void updatePartitionState(long clusterGenerationId, Partition partition, List<DegraderTrackerClient> trackerClients, DegraderLoadBalancerStrategyConfig config) {
    PartitionDegraderLoadBalancerState partitionState = partition.getState();
    List<DegraderTrackerClientUpdater> clientUpdaters = new ArrayList<>();
    for (DegraderTrackerClient client : trackerClients) {
        clientUpdaters.add(new DegraderTrackerClientUpdater(client, partition.getId()));
    }
    boolean quarantineEnabled = _state.isQuarantineEnabled();
    if (config.getQuarantineMaxPercent() > 0.0 && !quarantineEnabled) {
        // check the hosts to see if the quarantine can be enabled.
        if (_state.incrementAndGetQuarantineRetries() <= MAX_RETRIES_TO_CHECK_QUARANTINE) {
            _config.getExecutorService().submit(() -> checkQuarantineState(clientUpdaters, config));
        }
    }
    // doUpdatePartitionState has no side effects on _state or trackerClients.
    // all changes to the trackerClients would be recorded in clientUpdaters
    partitionState = doUpdatePartitionState(clusterGenerationId, partition.getId(), partitionState, config, clientUpdaters, quarantineEnabled);
    partition.setState(partitionState);
    // only if state update succeeded, do we actually apply the recorded changes to trackerClients
    for (DegraderTrackerClientUpdater clientUpdater : clientUpdaters) {
        clientUpdater.update();
    }
}
Also used : DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient) ArrayList(java.util.ArrayList)

Example 3 with DegraderTrackerClient

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

the class DegraderLoadBalancerStrategyV3 method getTrackerClient.

@Override
public TrackerClient getTrackerClient(Request request, RequestContext requestContext, long clusterGenerationId, int partitionId, Map<URI, TrackerClient> trackerClients, boolean shouldForceUpdate) {
    debug(_log, "getTrackerClient with generation id ", clusterGenerationId, " partition id: ", partitionId, " on tracker clients: ", trackerClients);
    if (trackerClients == null || trackerClients.size() == 0) {
        warn(_log, "getTrackerClient called with null/empty trackerClients, so returning null");
        return null;
    }
    List<DegraderTrackerClient> degraderTrackerClients = castToDegraderTrackerClients(trackerClients);
    // only one thread will be allowed to enter updatePartitionState for any partition
    TimingContextUtil.markTiming(requestContext, TIMING_KEY);
    checkUpdatePartitionState(clusterGenerationId, partitionId, degraderTrackerClients, shouldForceUpdate);
    TimingContextUtil.markTiming(requestContext, TIMING_KEY);
    Ring<URI> ring = _state.getRing(partitionId);
    URI targetHostUri = KeyMapper.TargetHostHints.getRequestContextTargetHost(requestContext);
    Set<URI> excludedUris = ExcludedHostHints.getRequestContextExcludedHosts(requestContext);
    if (excludedUris == null) {
        excludedUris = new HashSet<>();
    }
    // no valid target host header was found in the request
    DegraderTrackerClient client;
    if (targetHostUri == null) {
        client = findValidClientFromRing(request, ring, degraderTrackerClients, excludedUris, requestContext);
    } else {
        debug(_log, "Degrader honoring target host header in request, skipping hashing.  URI: ", targetHostUri);
        client = searchClientFromUri(targetHostUri, degraderTrackerClients);
        if (client == null) {
            warn(_log, "No client found for ", targetHostUri, ". Target host specified is no longer part of cluster");
        } else {
            // if this flag is set to be true, that means affinity routing is preferred but backup requests are still acceptable
            Boolean otherHostAcceptable = KeyMapper.TargetHostHints.getRequestContextOtherHostAcceptable(requestContext);
            if (otherHostAcceptable != null && otherHostAcceptable) {
                ExcludedHostHints.addRequestContextExcludedHost(requestContext, targetHostUri);
            }
        }
    }
    if (client == null) {
        return null;
    }
    // Decides whether to drop the call
    Degrader degrader = client.getDegrader(partitionId);
    if (degrader.checkDrop()) {
        warn(_log, "client's degrader is dropping call for: ", client);
        return null;
    }
    debug(_log, "returning client: ", client);
    // Decides whether to degrade call at the transport layer
    if (degrader.checkPreemptiveTimeout()) {
        DegraderControl degraderControl = client.getDegraderControl(partitionId);
        requestContext.putLocalAttr(R2Constants.PREEMPTIVE_TIMEOUT_RATE, degraderControl.getPreemptiveRequestTimeoutRate());
    }
    return client;
}
Also used : Degrader(com.linkedin.util.degrader.Degrader) DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient) DegraderControl(com.linkedin.util.degrader.DegraderControl) URI(java.net.URI)

Example 4 with DegraderTrackerClient

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

the class DegraderTrackerClientTest method testDoNotSlowStartWhenFalse.

@Test
public void testDoNotSlowStartWhenFalse() {
    Map<Integer, PartitionData> partitionDataMap = createDefaultPartitionData(1d);
    DegraderImpl.Config config = new DegraderImpl.Config();
    double initialDropRate = 0.99d;
    config.setInitialDropRate(initialDropRate);
    DegraderTrackerClient client = new DegraderTrackerClientImpl(URI.create("http://test.qa.com:1234/foo"), partitionDataMap, new TestClient(), new SettableClock(), config, DegraderLoadBalancerStrategyConfig.DEFAULT_UPDATE_INTERVAL_MS, TrackerClientImpl.DEFAULT_ERROR_STATUS_PATTERN, false);
    DegraderControl degraderControl = client.getDegraderControl(DefaultPartitionAccessor.DEFAULT_PARTITION_ID);
    Assert.assertEquals(degraderControl.getInitialDropRate(), initialDropRate, "Initial drop rate in config should not have been overridden by doNotSlowStart uri property.");
}
Also used : AtomicInteger(java.util.concurrent.atomic.AtomicInteger) PartitionData(com.linkedin.d2.balancer.properties.PartitionData) DegraderLoadBalancerStrategyConfig(com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerStrategyConfig) DegraderImpl(com.linkedin.util.degrader.DegraderImpl) DegraderControl(com.linkedin.util.degrader.DegraderControl) SettableClock(com.linkedin.util.clock.SettableClock) Test(org.testng.annotations.Test)

Example 5 with DegraderTrackerClient

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

the class DegraderTrackerClientTest method testClientRestRequest.

@Test(groups = { "small", "back-end" })
public void testClientRestRequest() throws URISyntaxException {
    URI uri = URI.create("http://test.qa.com:1234/foo");
    double weight = 3d;
    TestClient wrappedClient = new TestClient();
    Clock clock = new SettableClock();
    Map<Integer, PartitionData> partitionDataMap = createDefaultPartitionData(3d);
    DegraderTrackerClient client = new DegraderTrackerClientImpl(uri, partitionDataMap, wrappedClient, clock, null);
    Assert.assertEquals(client.getUri(), uri);
    Double clientWeight = client.getPartitionWeight(DefaultPartitionAccessor.DEFAULT_PARTITION_ID);
    Assert.assertEquals(clientWeight, weight);
    Assert.assertEquals(client.getTransportClient(), wrappedClient);
    RestRequest restRequest = new RestRequestBuilder(uri).build();
    Map<String, String> restWireAttrs = new HashMap<>();
    TestTransportCallback<RestResponse> restCallback = new TestTransportCallback<>();
    client.restRequest(restRequest, new RequestContext(), restWireAttrs, restCallback);
    Assert.assertFalse(restCallback.response.hasError());
    Assert.assertEquals(wrappedClient.restRequest, restRequest);
    Assert.assertEquals(wrappedClient.restWireAttrs, restWireAttrs);
}
Also used : HashMap(java.util.HashMap) RestResponse(com.linkedin.r2.message.rest.RestResponse) ByteString(com.linkedin.data.ByteString) Clock(com.linkedin.util.clock.Clock) SettableClock(com.linkedin.util.clock.SettableClock) URI(java.net.URI) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) RestRequest(com.linkedin.r2.message.rest.RestRequest) PartitionData(com.linkedin.d2.balancer.properties.PartitionData) SettableClock(com.linkedin.util.clock.SettableClock) RestRequestBuilder(com.linkedin.r2.message.rest.RestRequestBuilder) RequestContext(com.linkedin.r2.message.RequestContext) Test(org.testng.annotations.Test)

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