Search in sources :

Example 56 with Ring

use of com.linkedin.d2.balancer.util.hashing.Ring in project rest.li by linkedin.

the class RelativeLoadBalancerStrategyFactory method putDefaultValues.

static D2RelativeStrategyProperties putDefaultValues(D2RelativeStrategyProperties properties) {
    properties.setUpStep(getOrDefault(properties.getUpStep(), DEFAULT_UP_STEP));
    properties.setDownStep(getOrDefault(properties.getDownStep(), DEFAULT_DOWN_STEP));
    properties.setHighErrorRate(getOrDefault(properties.getHighErrorRate(), DEFAULT_HIGH_ERROR_RATE));
    properties.setLowErrorRate(getOrDefault(properties.getLowErrorRate(), DEFAULT_LOW_ERROR_RATE));
    properties.setRelativeLatencyHighThresholdFactor(getOrDefault(properties.getRelativeLatencyHighThresholdFactor(), DEFAULT_RELATIVE_LATENCY_HIGH_THRESHOLD_FACTOR));
    properties.setRelativeLatencyLowThresholdFactor(getOrDefault(properties.getRelativeLatencyLowThresholdFactor(), DEFAULT_RELATIVE_LATENCY_LOW_THRESHOLD_FACTOR));
    properties.setMinCallCount(getOrDefault(properties.getMinCallCount(), DEFAULT_MIN_CALL_COUNT));
    properties.setUpdateIntervalMs(getOrDefault(properties.getUpdateIntervalMs(), DEFAULT_UPDATE_INTERVAL_MS));
    properties.setInitialHealthScore(getOrDefault(properties.getInitialHealthScore(), DEFAULT_INITIAL_HEALTH_SCORE));
    properties.setSlowStartThreshold(getOrDefault(properties.getSlowStartThreshold(), DEFAULT_SLOW_START_THRESHOLD));
    properties.setErrorStatusFilter(getOrDefault(properties.getErrorStatusFilter(), DEFAULT_ERROR_STATUS_FILTER));
    properties.setEmittingIntervalMs(getOrDefault(properties.getEmittingIntervalMs(), DEFAULT_EMITTING_INTERVAL_MS));
    properties.setEnableFastRecovery(getOrDefault(properties.isEnableFastRecovery(), DEFAULT_ENABLE_FAST_RECOVERY));
    D2QuarantineProperties quarantineProperties = properties.hasQuarantineProperties() ? properties.getQuarantineProperties() : new D2QuarantineProperties();
    quarantineProperties.setQuarantineMaxPercent(getOrDefault(quarantineProperties.getQuarantineMaxPercent(), DEFAULT_QUARANTINE_MAX_PERCENT));
    quarantineProperties.setHealthCheckMethod(getOrDefault(quarantineProperties.getHealthCheckMethod(), DEFAULT_HTTP_METHOD));
    properties.setQuarantineProperties(quarantineProperties);
    // Most ring properties are initialized in {@link DelegatingRingFactory}
    D2RingProperties ringProperties = properties.hasRingProperties() ? properties.getRingProperties() : new D2RingProperties();
    ringProperties.setPointsPerWeight(getOrDefault(ringProperties.getPointsPerWeight(), DEFAULT_POINTS_PER_WEIGHT));
    properties.setRingProperties(ringProperties);
    return properties;
}
Also used : D2QuarantineProperties(com.linkedin.d2.D2QuarantineProperties) D2RingProperties(com.linkedin.d2.D2RingProperties)

Example 57 with Ring

use of com.linkedin.d2.balancer.util.hashing.Ring in project rest.li by linkedin.

the class DeterministicSubsettingStrategy method getWeightedSubset.

@Override
public Map<T, Double> getWeightedSubset(Map<T, Double> weightMap, DeterministicSubsettingMetadata metadata) {
    if (metadata != null) {
        List<T> points = new ArrayList<>(weightMap.keySet());
        Collections.sort(points);
        Collections.shuffle(points, new Random(_randomSeed));
        List<Double> weights = points.stream().map(weightMap::get).collect(Collectors.toList());
        double totalWeight = weights.stream().mapToDouble(Double::doubleValue).sum();
        if (totalWeight == 0) {
            return null;
        }
        Ring ring = new Ring(weights, totalWeight);
        double offset = metadata.getInstanceId() / (double) metadata.getTotalInstanceCount();
        double subsetSliceWidth = getSubsetSliceWidth(metadata.getTotalInstanceCount(), points.size());
        List<Integer> indices = ring.getIndices(offset, subsetSliceWidth);
        return indices.stream().collect(Collectors.toMap(points::get, i -> round(ring.getWeight(i, offset, subsetSliceWidth), WEIGHT_DECIMAL_PLACE)));
    } else {
        _log.warn("Cannot retrieve metadata required for D2 subsetting. Revert to use all available hosts.");
        return null;
    }
}
Also used : BigDecimal(java.math.BigDecimal) List(java.util.List) Logger(org.slf4j.Logger) MD5Hash(com.linkedin.d2.balancer.util.hashing.MD5Hash) LoadBalancerState(com.linkedin.d2.balancer.LoadBalancerState) Map(java.util.Map) LoggerFactory(org.slf4j.LoggerFactory) Random(java.util.Random) Collections(java.util.Collections) Collectors(java.util.stream.Collectors) RoundingMode(java.math.RoundingMode) ArrayList(java.util.ArrayList) Random(java.util.Random) ArrayList(java.util.ArrayList)

Example 58 with Ring

use of com.linkedin.d2.balancer.util.hashing.Ring in project rest.li by linkedin.

the class ConsistentHashKeyMapper method mapKeysV2.

@Override
public <K> MapKeyResult<URI, K> mapKeysV2(URI serviceUri, Iterable<K> keys) throws ServiceUnavailableException {
    // distribute keys to rings for partitions
    // Note that we assume the keys are partitioning keys
    MapKeyResult<Ring<URI>, K> keyToPartitionResult = _ringProvider.getRings(serviceUri, keys);
    Map<Ring<URI>, Collection<K>> ringToKeys = keyToPartitionResult.getMapResult();
    Map<URI, Collection<K>> result = new HashMap<>();
    Collection<MapKeyResult.UnmappedKey<K>> unmappedKeys = new ArrayList<>();
    // first collect unmappedkeys in ditributing keys to partitions
    unmappedKeys.addAll(keyToPartitionResult.getUnmappedKeys());
    // for each partition, distribute keys to different server uris
    for (Map.Entry<Ring<URI>, Collection<K>> entry : ringToKeys.entrySet()) {
        MapKeyResult<URI, K> keyToHostResult = doMapKeys(entry.getKey(), entry.getValue());
        // collect map key to host result
        Map<URI, Collection<K>> hostToKeys = keyToHostResult.getMapResult();
        for (Map.Entry<URI, Collection<K>> hostEntry : hostToKeys.entrySet()) {
            URI uri = hostEntry.getKey();
            Collection<K> collection = result.get(uri);
            if (collection == null) {
                collection = new ArrayList<>();
                result.put(uri, collection);
            }
            collection.addAll(hostEntry.getValue());
        }
        // collect unmapped keys
        unmappedKeys.addAll(keyToHostResult.getUnmappedKeys());
    }
    return new MapKeyResult<>(result, unmappedKeys);
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) URI(java.net.URI) Collection(java.util.Collection) HashMap(java.util.HashMap) Map(java.util.Map) MapKeyResult(com.linkedin.d2.balancer.util.MapKeyResult)

Example 59 with Ring

use of com.linkedin.d2.balancer.util.hashing.Ring in project rest.li by linkedin.

the class DegraderLoadBalancerTest method testAdjustedMinCallCount.

@Test(groups = { "small", "back-end" })
public void testAdjustedMinCallCount() {
    final int NUM_CHECKS = 5;
    final Long TIME_INTERVAL = 5000L;
    Map<String, Object> myMap = lbDefaultConfig();
    // myMap.put(PropertyKeys.LB_INITIAL_RECOVERY_LEVEL, 0.01);
    // myMap.put("rampFactor", 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, DEGRADER_STATE_LISTENER_FACTORIES);
    List<DegraderTrackerClient> clients = new ArrayList<>();
    URI uri1 = URI.create("http://test.linkedin.com:3242/fdsaf");
    URIRequest request = new URIRequest(uri1);
    List<CallCompletion> ccList = new ArrayList<>();
    CallCompletion cc;
    DegraderTrackerClient client1 = new DegraderTrackerClientImpl(uri1, getDefaultPartitionData(1d), new TestLoadBalancerClient(uri1), clock, null);
    clients.add(client1);
    // force client1 to be disabled if we encounter errors/high latency
    DegraderControl dcClient1Default = client1.getDegraderControl(DEFAULT_PARTITION_ID);
    dcClient1Default.setOverrideMinCallCount(5);
    dcClient1Default.setMinCallCount(5);
    dcClient1Default.setUpStep(1.0);
    dcClient1Default.setHighErrorRate(0);
    // Issue high latency calls to reduce client1 to the minimum number of hash points allowed.
    // (1 in this case)
    TrackerClient resultTC = getTrackerClient(strategy, request, new RequestContext(), 1, clients);
    assertNotNull(resultTC, "expected non-null trackerclient");
    for (int j = 0; j < NUM_CHECKS; j++) {
        cc = ((DegraderTrackerClient) resultTC).getCallTracker().startCall();
        ccList.add(cc);
    }
    clock.addMs(3500);
    for (int j = 0; j < NUM_CHECKS; j++) {
        cc = ccList.get(j);
        cc.endCall();
    }
    // bump to next interval, and get stats.
    clock.addMs(5000);
    // because we want to test out the adjusted min drop rate, force the hash ring adjustment now.
    strategy.setStrategy(DEFAULT_PARTITION_ID, PartitionDegraderLoadBalancerState.Strategy.LOAD_BALANCE);
    resultTC = getTrackerClient(strategy, request, new RequestContext(), 1, clients);
    // client1 should be reduced to 1 hash point, but since it is the only TC, it should be the
    // TC returned.
    assertEquals(resultTC, client1, "expected non-null trackerclient");
    assertEquals((int) (strategy.getState().getPartitionState(DEFAULT_PARTITION_ID).getPointsMap().get(client1.getUri())), 1, "expected client1 to have only 1 point in hash map");
    // make low latency call, we expect the computedDropRate to be adjusted because the minimum
    // call count was also scaled down.
    cc = client1.getCallTracker().startCall();
    clock.addMs(10);
    cc.endCall();
    clock.addMs(TIME_INTERVAL);
    Assert.assertTrue(dcClient1Default.getCurrentComputedDropRate() < 1.0, "client1 drop rate not less than 1.");
}
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 60 with Ring

use of com.linkedin.d2.balancer.util.hashing.Ring in project rest.li by linkedin.

the class DegraderLoadBalancerTest method testClientGlitch.

@Test(groups = { "small", "back-end" }, dataProvider = "clientGlitch", enabled = false)
public /**
 * The strategy recovers after a TrackerClient throws one Exception.
 */
void testClientGlitch(final int numberOfPartitions, final LoadBalancerStrategy strategy, final TestClock clock, final long timeInterval) throws Exception {
    final List<DegraderTrackerClient> client = Collections.singletonList(new ErrorClient(1, numberOfPartitions, clock));
    final int partitionId = DefaultPartitionAccessor.DEFAULT_PARTITION_ID + numberOfPartitions - 1;
    final Callable<Ring<URI>> getRing = new Callable<Ring<URI>>() {

        @Override
        public Ring<URI> call() {
            return strategy.getRing(1L, partitionId, toMap(client));
        }
    };
    try {
        // initialization
        getRing.call();
        fail("no glitch");
    } catch (DummyCheckedException expectedGlitch) {
    }
    final int numberOfThreads = 5;
    final ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);
    try {
        final List<Future<Ring<URI>>> results = new ArrayList<>();
        for (int r = 0; r < numberOfThreads; ++r) results.add(executor.submit(getRing));
        clock.addMs(timeInterval);
        // During this time,
        Thread.sleep(timeInterval * 2);
        // one of the threads should initialize the partition state,
        // and then all of the threads should get the new ring.
        assertEquals(countDone(results), results.size());
    } finally {
        executor.shutdownNow();
    }
}
Also used : DegraderTrackerClient(com.linkedin.d2.balancer.clients.DegraderTrackerClient) ArrayList(java.util.ArrayList) URI(java.net.URI) Callable(java.util.concurrent.Callable) Ring(com.linkedin.d2.balancer.util.hashing.Ring) ExecutorService(java.util.concurrent.ExecutorService) Future(java.util.concurrent.Future) Test(org.testng.annotations.Test) DegraderTrackerClientTest(com.linkedin.d2.balancer.clients.DegraderTrackerClientTest)

Aggregations

URI (java.net.URI)48 HashMap (java.util.HashMap)31 TrackerClient (com.linkedin.d2.balancer.clients.TrackerClient)30 Test (org.testng.annotations.Test)26 ArrayList (java.util.ArrayList)25 Map (java.util.Map)21 URIRequest (com.linkedin.d2.balancer.util.URIRequest)15 HashSet (java.util.HashSet)15 DegraderTrackerClient (com.linkedin.d2.balancer.clients.DegraderTrackerClient)14 RequestContext (com.linkedin.r2.message.RequestContext)14 List (java.util.List)12 PartitionAccessor (com.linkedin.d2.balancer.util.partitions.PartitionAccessor)10 LoadBalancerState (com.linkedin.d2.balancer.LoadBalancerState)9 ServiceUnavailableException (com.linkedin.d2.balancer.ServiceUnavailableException)9 Request (com.linkedin.r2.message.Request)9 DegraderControl (com.linkedin.util.degrader.DegraderControl)9 Set (java.util.Set)9 DegraderTrackerClientTest (com.linkedin.d2.balancer.clients.DegraderTrackerClientTest)8 Ring (com.linkedin.d2.balancer.util.hashing.Ring)8 LoadBalancerStrategy (com.linkedin.d2.balancer.strategies.LoadBalancerStrategy)7