Search in sources :

Example 96 with TrackerClient

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

the class SimpleLoadBalancerStateTest method testClientsShutdownAfterPropertyUpdatesRestRequest.

@Test(groups = { "small", "back-end" })
public void testClientsShutdownAfterPropertyUpdatesRestRequest() throws URISyntaxException, InterruptedException {
    reset();
    URI uri = URI.create("http://cluster-1/test");
    List<String> schemes = new ArrayList<>();
    Map<Integer, PartitionData> partitionData = new HashMap<>(1);
    partitionData.put(DefaultPartitionAccessor.DEFAULT_PARTITION_ID, new PartitionData(1d));
    Map<URI, Map<Integer, PartitionData>> uriData = new HashMap<>();
    uriData.put(uri, partitionData);
    schemes.add("http");
    // set up state
    _state.listenToService("service-1", new NullStateListenerCallback());
    _state.listenToCluster("cluster-1", new NullStateListenerCallback());
    _state.setDelayedExecution(0);
    _serviceRegistry.put("service-1", new ServiceProperties("service-1", "cluster-1", "/test", Arrays.asList("random"), Collections.<String, Object>emptyMap(), Collections.<String, Object>emptyMap(), Collections.<String, String>emptyMap(), schemes, Collections.<URI>emptySet()));
    _clusterRegistry.put("cluster-1", new ClusterProperties("cluster-1"));
    _uriRegistry.put("cluster-1", new UriProperties("cluster-1", uriData));
    URI uri1 = URI.create("http://partition-cluster-1/test1");
    URI uri2 = URI.create("http://partition-cluster-1/test2");
    _state.listenToCluster("partition-cluster-1", new NullStateListenerCallback());
    _clusterRegistry.put("partition-cluster-1", new ClusterProperties("partition-cluster-1", null, new HashMap<>(), new HashSet<>(), new RangeBasedPartitionProperties("id=(\\d+)", 0, 100, 2)));
    _state.listenToService("partition-service-1", new NullStateListenerCallback());
    _serviceRegistry.put("partition-service-1", new ServiceProperties("partition-service-1", "partition-cluster-1", "/partition-test", Arrays.asList("degraderV3"), Collections.<String, Object>emptyMap(), Collections.<String, Object>emptyMap(), Collections.<String, String>emptyMap(), schemes, Collections.<URI>emptySet()));
    Map<Integer, PartitionData> partitionWeight = new HashMap<>();
    partitionWeight.put(0, new PartitionData(1d));
    partitionWeight.put(1, new PartitionData(2d));
    Map<URI, Map<Integer, PartitionData>> partitionDesc = new HashMap<>();
    partitionDesc.put(uri1, partitionWeight);
    partitionWeight.remove(0);
    partitionWeight.put(2, new PartitionData(1d));
    partitionDesc.put(uri2, partitionWeight);
    _uriRegistry.put("partition-cluster-1", new UriProperties("partition-cluster-1", partitionDesc));
    TrackerClient client1 = _state.getClient("partition-service-1", uri1);
    TrackerClient client2 = _state.getClient("partition-service-1", uri2);
    assertEquals(client2.getPartitionWeight(1), 2d);
    assertEquals(client2.getPartitionWeight(2), 1d);
    assertEquals(client1.getPartitionWeight(1), 2d);
    // Get client, then refresh cluster
    TrackerClient client = _state.getClient("service-1", uri);
    client.restRequest(new RestRequestBuilder(URI.create("d2://service-1/foo")).build(), new RequestContext(), Collections.emptyMap(), new TransportCallbackAdapter<>(Callbacks.empty()));
    // now force a refresh by adding cluster
    _clusterRegistry.put("cluster-1", new ClusterProperties("cluster-1"));
    // Get client, then refresh service
    client = _state.getClient("service-1", uri);
    client.restRequest(new RestRequestBuilder(URI.create("d2://service-1/foo")).build(), new RequestContext(), Collections.emptyMap(), new TransportCallbackAdapter<>(Callbacks.empty()));
    // refresh by adding service
    _serviceRegistry.put("service-1", new ServiceProperties("service-1", "cluster-1", "/test", Arrays.asList("random"), Collections.<String, Object>emptyMap(), null, null, schemes, null));
    // Get client, then mark server up/down
    client = _state.getClient("service-1", uri);
    client.restRequest(new RestRequestBuilder(URI.create("d2://service-1/foo")).build(), new RequestContext(), Collections.emptyMap(), new TransportCallbackAdapter<>(Callbacks.empty()));
    _uriRegistry.put("cluster-1", new UriProperties("cluster-1", Collections.<URI, Map<Integer, PartitionData>>emptyMap()));
    _uriRegistry.put("cluster-1", new UriProperties("cluster-1", uriData));
    // Get the client one last time
    client = _state.getClient("service-1", uri);
    client.restRequest(new RestRequestBuilder(URI.create("d2://service-1/foo")).build(), new RequestContext(), Collections.emptyMap(), new TransportCallbackAdapter<>(Callbacks.empty()));
    TestShutdownCallback callback = new TestShutdownCallback();
    _state.shutdown(callback);
    assertTrue(callback.await(10, TimeUnit.SECONDS), "Failed to shut down state");
    for (TransportClientFactory factory : _clientFactories.values()) {
        SimpleLoadBalancerTest.DoNothingClientFactory f = (SimpleLoadBalancerTest.DoNothingClientFactory) factory;
        assertEquals(f.getRunningClientCount(), 0, "not all clients were shut down");
    }
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) URI(java.net.URI) TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) PartitionData(com.linkedin.d2.balancer.properties.PartitionData) UriProperties(com.linkedin.d2.balancer.properties.UriProperties) RangeBasedPartitionProperties(com.linkedin.d2.balancer.properties.RangeBasedPartitionProperties) RequestContext(com.linkedin.r2.message.RequestContext) TransportClientFactory(com.linkedin.r2.transport.common.TransportClientFactory) HashSet(java.util.HashSet) NullStateListenerCallback(com.linkedin.d2.balancer.LoadBalancerState.NullStateListenerCallback) ServiceProperties(com.linkedin.d2.balancer.properties.ServiceProperties) ClusterProperties(com.linkedin.d2.balancer.properties.ClusterProperties) RestRequestBuilder(com.linkedin.r2.message.rest.RestRequestBuilder) Map(java.util.Map) HashMap(java.util.HashMap) Test(org.testng.annotations.Test) DegraderLoadBalancerTest(com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerTest)

Example 97 with TrackerClient

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

the class SimpleLoadBalancerStateTest method testClientsShutdownAfterPropertyUpdatesStreamRequest.

@Test(groups = { "small", "back-end" })
public void testClientsShutdownAfterPropertyUpdatesStreamRequest() throws URISyntaxException, InterruptedException {
    reset();
    URI uri = URI.create("http://cluster-1/test");
    List<String> schemes = new ArrayList<>();
    Map<Integer, PartitionData> partitionData = new HashMap<>(1);
    partitionData.put(DefaultPartitionAccessor.DEFAULT_PARTITION_ID, new PartitionData(1d));
    Map<URI, Map<Integer, PartitionData>> uriData = new HashMap<>();
    uriData.put(uri, partitionData);
    schemes.add("http");
    // set up state
    _state.listenToService("service-1", new NullStateListenerCallback());
    _state.listenToCluster("cluster-1", new NullStateListenerCallback());
    _state.setDelayedExecution(0);
    _serviceRegistry.put("service-1", new ServiceProperties("service-1", "cluster-1", "/test", Arrays.asList("random"), Collections.<String, Object>emptyMap(), Collections.<String, Object>emptyMap(), Collections.<String, String>emptyMap(), schemes, Collections.<URI>emptySet()));
    _clusterRegistry.put("cluster-1", new ClusterProperties("cluster-1"));
    _uriRegistry.put("cluster-1", new UriProperties("cluster-1", uriData));
    URI uri1 = URI.create("http://partition-cluster-1/test1");
    URI uri2 = URI.create("http://partition-cluster-1/test2");
    _state.listenToCluster("partition-cluster-1", new NullStateListenerCallback());
    _clusterRegistry.put("partition-cluster-1", new ClusterProperties("partition-cluster-1", null, new HashMap<>(), new HashSet<>(), new RangeBasedPartitionProperties("id=(\\d+)", 0, 100, 2)));
    _state.listenToService("partition-service-1", new NullStateListenerCallback());
    _serviceRegistry.put("partition-service-1", new ServiceProperties("partition-service-1", "partition-cluster-1", "/partition-test", Arrays.asList("degraderV3"), Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap(), schemes, Collections.emptySet()));
    Map<Integer, PartitionData> partitionWeight = new HashMap<>();
    partitionWeight.put(0, new PartitionData(1d));
    partitionWeight.put(1, new PartitionData(2d));
    Map<URI, Map<Integer, PartitionData>> partitionDesc = new HashMap<>();
    partitionDesc.put(uri1, partitionWeight);
    partitionWeight.remove(0);
    partitionWeight.put(2, new PartitionData(1d));
    partitionDesc.put(uri2, partitionWeight);
    _uriRegistry.put("partition-cluster-1", new UriProperties("partition-cluster-1", partitionDesc));
    TrackerClient client1 = _state.getClient("partition-service-1", uri1);
    TrackerClient client2 = _state.getClient("partition-service-1", uri2);
    assertEquals(client2.getPartitionWeight(1), 2d);
    assertEquals(client2.getPartitionWeight(2), 1d);
    assertEquals(client1.getPartitionWeight(1), 2d);
    // Get client, then refresh cluster
    TrackerClient client = _state.getClient("service-1", uri);
    client.streamRequest(new StreamRequestBuilder(URI.create("d2://service-1/foo")).build(EntityStreams.emptyStream()), new RequestContext(), Collections.emptyMap(), new TransportCallbackAdapter<>(Callbacks.empty()));
    // now force a refresh by adding cluster
    _clusterRegistry.put("cluster-1", new ClusterProperties("cluster-1"));
    // Get client, then refresh service
    client = _state.getClient("service-1", uri);
    client.streamRequest(new StreamRequestBuilder(URI.create("d2://service-1/foo")).build(EntityStreams.emptyStream()), new RequestContext(), Collections.emptyMap(), new TransportCallbackAdapter<>(Callbacks.empty()));
    // refresh by adding service
    _serviceRegistry.put("service-1", new ServiceProperties("service-1", "cluster-1", "/test", Arrays.asList("random"), Collections.<String, Object>emptyMap(), null, null, schemes, null));
    // Get client, then mark server up/down
    client = _state.getClient("service-1", uri);
    client.streamRequest(new StreamRequestBuilder(URI.create("d2://service-1/foo")).build(EntityStreams.emptyStream()), new RequestContext(), Collections.emptyMap(), new TransportCallbackAdapter<>(Callbacks.empty()));
    _uriRegistry.put("cluster-1", new UriProperties("cluster-1", Collections.<URI, Map<Integer, PartitionData>>emptyMap()));
    _uriRegistry.put("cluster-1", new UriProperties("cluster-1", uriData));
    // Get the client one last time
    client = _state.getClient("service-1", uri);
    client.streamRequest(new StreamRequestBuilder(URI.create("d2://service-1/foo")).build(EntityStreams.emptyStream()), new RequestContext(), Collections.emptyMap(), new TransportCallbackAdapter<>(Callbacks.empty()));
    TestShutdownCallback callback = new TestShutdownCallback();
    _state.shutdown(callback);
    assertTrue(callback.await(10, TimeUnit.SECONDS), "Failed to shut down state");
    for (TransportClientFactory factory : _clientFactories.values()) {
        SimpleLoadBalancerTest.DoNothingClientFactory f = (SimpleLoadBalancerTest.DoNothingClientFactory) factory;
        assertEquals(f.getRunningClientCount(), 0, "not all clients were shut down");
    }
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) URI(java.net.URI) StreamRequestBuilder(com.linkedin.r2.message.stream.StreamRequestBuilder) TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) PartitionData(com.linkedin.d2.balancer.properties.PartitionData) UriProperties(com.linkedin.d2.balancer.properties.UriProperties) RangeBasedPartitionProperties(com.linkedin.d2.balancer.properties.RangeBasedPartitionProperties) RequestContext(com.linkedin.r2.message.RequestContext) TransportClientFactory(com.linkedin.r2.transport.common.TransportClientFactory) HashSet(java.util.HashSet) NullStateListenerCallback(com.linkedin.d2.balancer.LoadBalancerState.NullStateListenerCallback) ServiceProperties(com.linkedin.d2.balancer.properties.ServiceProperties) ClusterProperties(com.linkedin.d2.balancer.properties.ClusterProperties) Map(java.util.Map) HashMap(java.util.HashMap) Test(org.testng.annotations.Test) DegraderLoadBalancerTest(com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerTest)

Example 98 with TrackerClient

use of com.linkedin.d2.balancer.clients.TrackerClient 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 99 with TrackerClient

use of com.linkedin.d2.balancer.clients.TrackerClient 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 100 with TrackerClient

use of com.linkedin.d2.balancer.clients.TrackerClient 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

TrackerClient (com.linkedin.d2.balancer.clients.TrackerClient)117 URI (java.net.URI)83 Test (org.testng.annotations.Test)58 HashMap (java.util.HashMap)50 ArrayList (java.util.ArrayList)49 RequestContext (com.linkedin.r2.message.RequestContext)39 PartitionData (com.linkedin.d2.balancer.properties.PartitionData)30 DegraderTrackerClient (com.linkedin.d2.balancer.clients.DegraderTrackerClient)26 Map (java.util.Map)25 ServiceProperties (com.linkedin.d2.balancer.properties.ServiceProperties)22 DegraderTrackerClientImpl (com.linkedin.d2.balancer.clients.DegraderTrackerClientImpl)18 UriProperties (com.linkedin.d2.balancer.properties.UriProperties)18 D2RelativeStrategyProperties (com.linkedin.d2.D2RelativeStrategyProperties)17 DegraderTrackerClientTest (com.linkedin.d2.balancer.clients.DegraderTrackerClientTest)17 NullStateListenerCallback (com.linkedin.d2.balancer.LoadBalancerState.NullStateListenerCallback)15 DegraderLoadBalancerTest (com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerTest)14 URIRequest (com.linkedin.d2.balancer.util.URIRequest)14 DegraderControl (com.linkedin.util.degrader.DegraderControl)14 HashSet (java.util.HashSet)13 LoadBalancerStrategy (com.linkedin.d2.balancer.strategies.LoadBalancerStrategy)12