use of com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerStrategyConfig in project rest.li by linkedin.
the class RetryClientTest method prepareLoadBalancer.
public SimpleLoadBalancer prepareLoadBalancer(List<String> uris, double maxClientRequestRetryRatio) throws URISyntaxException {
String serviceName = "retryService";
String clusterName = "cluster";
String path = "";
String strategyName = "degrader";
// setup partition
Map<URI, Map<Integer, PartitionData>> partitionDescriptions = new HashMap<>();
for (String uri : uris) {
final URI foo = URI.create(uri);
Map<Integer, PartitionData> foo1Data = new HashMap<>();
// ensure that we first route to the retry uris before the good uris
double weight = uri.contains("good") ? 0.1 : 1.0;
foo1Data.put(0, new PartitionData(weight));
partitionDescriptions.put(foo, foo1Data);
}
DegraderLoadBalancerStrategyV3 strategy = new DegraderLoadBalancerStrategyV3(new DegraderLoadBalancerStrategyConfig(5000), serviceName, null, Collections.emptyList());
List<LoadBalancerState.SchemeStrategyPair> orderedStrategies = new ArrayList<>();
orderedStrategies.add(new LoadBalancerState.SchemeStrategyPair("http", strategy));
PartitionAccessor accessor = new TestRetryPartitionAccessor();
SimpleLoadBalancer balancer = new SimpleLoadBalancer(new PartitionedLoadBalancerTestState(clusterName, serviceName, path, strategyName, partitionDescriptions, orderedStrategies, accessor, maxClientRequestRetryRatio), _executor);
return balancer;
}
use of com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerStrategyConfig in project rest.li by linkedin.
the class DegraderLoadBalancerTest method testshouldUpdatePartition.
@Test(groups = { "small", "back-end" })
public void testshouldUpdatePartition() throws URISyntaxException {
Map<String, Object> myConfig = new HashMap<>();
TestClock testClock = new TestClock();
myConfig.put(PropertyKeys.CLOCK, testClock);
myConfig.put(PropertyKeys.HTTP_LB_STRATEGY_PROPERTIES_UPDATE_INTERVAL_MS, 5000L);
myConfig.put(PropertyKeys.HTTP_LB_STRATEGY_PROPERTIES_MAX_CLUSTER_LATENCY_WITHOUT_DEGRADING, 100d);
DegraderLoadBalancerStrategyV3 strategy = getStrategy(myConfig);
List<DegraderTrackerClient> clients = new ArrayList<>();
Map<URI, Integer> pointsMap = new HashMap<>();
long clusterCallCount = 15;
RingFactory<URI> ringFactory = new DelegatingRingFactory<>(new DegraderLoadBalancerStrategyConfig(1L));
URI uri1 = URI.create("http://test.linkedin.com:3242/fdsaf");
URI uri2 = URI.create("http://test.linkedin.com:3243/fdsaf");
clients.add(getClient(uri1));
clients.add(getClient(uri2));
pointsMap.put(uri1, 1);
pointsMap.put(uri2, 1);
// state is default initialized, new cluster generation
assertTrue(DegraderLoadBalancerStrategyV3.shouldUpdatePartition(0, strategy.getState().getPartitionState(DEFAULT_PARTITION_ID), strategy.getConfig(), true, false, clients));
PartitionDegraderLoadBalancerState current = strategy.getState().getPartitionState(DEFAULT_PARTITION_ID);
current = new PartitionDegraderLoadBalancerState(0, testClock._currentTimeMillis, true, ringFactory, pointsMap, PartitionDegraderLoadBalancerState.Strategy.LOAD_BALANCE, 0.0, -1, new HashMap<>(), "Test", current.getDegraderProperties(), clusterCallCount, 0, 0, Collections.emptyMap(), Collections.emptyMap(), null, 0);
strategy.getState().setPartitionState(DEFAULT_PARTITION_ID, current);
// state is not null, but we're on the same cluster generation id, and 5 seconds
// haven't gone by
testClock.addMs(1);
assertFalse(DegraderLoadBalancerStrategyV3.shouldUpdatePartition(0, strategy.getState().getPartitionState(DEFAULT_PARTITION_ID), strategy.getConfig(), true, false, clients));
// generation Id for the next state is changed
current = new PartitionDegraderLoadBalancerState(1, testClock._currentTimeMillis, true, ringFactory, pointsMap, PartitionDegraderLoadBalancerState.Strategy.LOAD_BALANCE, 0.0, -1, new HashMap<>(), "Test", current.getDegraderProperties(), clusterCallCount, 0, 0, Collections.emptyMap(), Collections.emptyMap(), null, 0);
strategy.getState().setPartitionState(DEFAULT_PARTITION_ID, current);
// state is not null, and cluster generation has changed so we will update
testClock.addMs(1);
assertTrue(DegraderLoadBalancerStrategyV3.shouldUpdatePartition(0, strategy.getState().getPartitionState(DEFAULT_PARTITION_ID), strategy.getConfig(), true, false, clients));
// state is not null, and force 5s to go by with the same cluster generation id
current = new PartitionDegraderLoadBalancerState(1, testClock._currentTimeMillis, true, ringFactory, pointsMap, PartitionDegraderLoadBalancerState.Strategy.LOAD_BALANCE, 0.0, -1, new HashMap<>(), "Test", current.getDegraderProperties(), clusterCallCount, 0, 0, Collections.emptyMap(), Collections.emptyMap(), null, 0);
strategy.getState().setPartitionState(DEFAULT_PARTITION_ID, current);
testClock.addMs(5000);
assertTrue(DegraderLoadBalancerStrategyV3.shouldUpdatePartition(1, strategy.getState().getPartitionState(DEFAULT_PARTITION_ID), strategy.getConfig(), true, false, clients));
current = new PartitionDegraderLoadBalancerState(1, testClock._currentTimeMillis, true, ringFactory, pointsMap, PartitionDegraderLoadBalancerState.Strategy.LOAD_BALANCE, 0.0, -1, new HashMap<>(), "Test", current.getDegraderProperties(), clusterCallCount, 0, 0, Collections.emptyMap(), Collections.emptyMap(), null, 0);
strategy.getState().setPartitionState(DEFAULT_PARTITION_ID, current);
// now try a new cluster generation id so state will be updated again
testClock.addMs(15);
assertTrue(DegraderLoadBalancerStrategyV3.shouldUpdatePartition(2, strategy.getState().getPartitionState(DEFAULT_PARTITION_ID), strategy.getConfig(), true, false, clients));
}
use of com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerStrategyConfig in project rest.li by linkedin.
the class DegraderLoadBalancerTest method testshouldUpdatePartitionOnlyAtInterval.
@Test(groups = { "small", "back-end" })
public void testshouldUpdatePartitionOnlyAtInterval() throws URISyntaxException {
Map<String, Object> myConfig = new HashMap<>();
TestClock testClock = new TestClock();
myConfig.put(PropertyKeys.CLOCK, testClock);
myConfig.put(PropertyKeys.HTTP_LB_STRATEGY_PROPERTIES_UPDATE_INTERVAL_MS, 5000L);
myConfig.put(PropertyKeys.HTTP_LB_STRATEGY_PROPERTIES_MAX_CLUSTER_LATENCY_WITHOUT_DEGRADING, 100d);
myConfig.put(PropertyKeys.HTTP_LB_STRATEGY_PROPERTIES_UPDATE_ONLY_AT_INTERVAL, true);
DegraderLoadBalancerStrategyV3 strategy = getStrategy(myConfig);
List<DegraderTrackerClient> clients = new ArrayList<>();
Map<URI, Integer> pointsMap = new HashMap<>();
long clusterCallCount = 15;
RingFactory<URI> ringFactory = new DelegatingRingFactory<>(new DegraderLoadBalancerStrategyConfig(1L));
URI uri1 = URI.create("http://test.linkedin.com:3242/fdsaf");
URI uri2 = URI.create("http://test.linkedin.com:3243/fdsaf");
clients.add(getClient(uri1));
clients.add(getClient(uri2));
pointsMap.put(uri1, 1);
pointsMap.put(uri2, 1);
PartitionDegraderLoadBalancerState current = strategy.getState().getPartitionState(DEFAULT_PARTITION_ID);
current = new PartitionDegraderLoadBalancerState(0, testClock._currentTimeMillis, true, ringFactory, pointsMap, PartitionDegraderLoadBalancerState.Strategy.LOAD_BALANCE, 0.0, -1, new HashMap<>(), "Test", current.getDegraderProperties(), clusterCallCount, 0, 0, Collections.emptyMap(), Collections.emptyMap(), null, 0);
strategy.getState().setPartitionState(DEFAULT_PARTITION_ID, current);
// state is default initialized, new cluster generation
assertFalse(DegraderLoadBalancerStrategyV3.shouldUpdatePartition(0, strategy.getState().getPartitionState(DEFAULT_PARTITION_ID), strategy.getConfig(), true, false, clients));
// state is not null, but we're on the same cluster generation id, and 5 seconds
// haven't gone by
testClock.addMs(1);
assertFalse(DegraderLoadBalancerStrategyV3.shouldUpdatePartition(0, strategy.getState().getPartitionState(DEFAULT_PARTITION_ID), strategy.getConfig(), true, false, clients));
testClock.addMs(5000);
assertTrue(DegraderLoadBalancerStrategyV3.shouldUpdatePartition(1, strategy.getState().getPartitionState(DEFAULT_PARTITION_ID), strategy.getConfig(), true, false, clients));
current = new PartitionDegraderLoadBalancerState(1, testClock._currentTimeMillis, true, new DelegatingRingFactory<>(new DegraderLoadBalancerStrategyConfig(1L)), pointsMap, PartitionDegraderLoadBalancerState.Strategy.LOAD_BALANCE, 0.0, -1, new HashMap<>(), "Test", current.getDegraderProperties(), clusterCallCount, 0, 0, Collections.emptyMap(), Collections.emptyMap(), null, 0);
strategy.getState().setPartitionState(DEFAULT_PARTITION_ID, current);
}
use of com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerStrategyConfig in project rest.li by linkedin.
the class DegraderLoadBalancerTest method testLowTrafficHighLatency100Clients.
@Test(groups = { "small", "back-end" })
public void testLowTrafficHighLatency100Clients() {
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(100, 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);
}
use of com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerStrategyConfig 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.");
}
Aggregations