use of com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerStrategyV3 in project rest.li by linkedin.
the class DegraderLoadBalancerTest method testRegexHashingConsistency.
@Test(groups = { "small", "back-end" })
public void testRegexHashingConsistency() {
final int NUM_SERVERS = 100;
DegraderLoadBalancerStrategyV3 strategy = new DegraderLoadBalancerStrategyV3(new DegraderLoadBalancerStrategyConfig(5000, true, 100, DegraderLoadBalancerStrategyV3.HASH_METHOD_URI_REGEX, Collections.<String, Object>singletonMap(URIRegexHash.KEY_REGEXES, Collections.singletonList("(.*)")), SystemClock.instance(), DegraderLoadBalancerStrategyConfig.DEFAULT_INITIAL_RECOVERY_LEVEL, DegraderLoadBalancerStrategyConfig.DEFAULT_RAMP_FACTOR, DegraderLoadBalancerStrategyConfig.DEFAULT_HIGH_WATER_MARK, DegraderLoadBalancerStrategyConfig.DEFAULT_LOW_WATER_MARK, DegraderLoadBalancerStrategyConfig.DEFAULT_GLOBAL_STEP_UP, DegraderLoadBalancerStrategyConfig.DEFAULT_GLOBAL_STEP_DOWN, DegraderLoadBalancerStrategyConfig.DEFAULT_CLUSTER_MIN_CALL_COUNT_HIGH_WATER_MARK, DegraderLoadBalancerStrategyConfig.DEFAULT_CLUSTER_MIN_CALL_COUNT_LOW_WATER_MARK, DegraderLoadBalancerStrategyConfig.DEFAULT_HASHRING_POINT_CLEANUP_RATE, null, DegraderLoadBalancerStrategyConfig.DEFAULT_NUM_PROBES, null, DegraderLoadBalancerStrategyConfig.DEFAULT_QUARANTINE_MAXPERCENT, null, null, DegraderLoadBalancerStrategyConfig.DEFAULT_QUARANTINE_METHOD, null, DegraderLoadBalancerStrategyConfig.DEFAULT_QUARANTINE_LATENCY), "DegraderLoadBalancerTest", null);
List<TrackerClient> clients = new ArrayList<TrackerClient>(NUM_SERVERS);
for (int i = 0; i < NUM_SERVERS; i++) {
clients.add(getClient(URI.create("http://server" + i + ".testing:9876/foobar")));
}
final int NUM_URIS = 1000;
final int NUM_CHECKS = 10;
final Map<TrackerClient, Integer> serverCounts = new HashMap<TrackerClient, Integer>();
for (int i = 0; i < NUM_URIS; i++) {
URIRequest request = new URIRequest("d2://fooService/this/is/a/test/" + i);
TrackerClient lastClient = null;
for (int j = 0; j < NUM_CHECKS; j++) {
TrackerClient client = getTrackerClient(strategy, request, new RequestContext(), 0, clients);
assertNotNull(client);
if (lastClient != null) {
assertEquals(client, lastClient);
}
lastClient = client;
}
Integer count = serverCounts.get(lastClient);
if (count == null) {
count = 0;
}
serverCounts.put(lastClient, count + 1);
}
// TODO... should check the distribution of hits/server, should be pretty even, but how
// even is even? Also note this depends on pointsPerServer and other configurable parameters.
// TODO... another test will check that when a TrackerClient is removed, the distribution
// doesn't change too much.
}
use of com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerStrategyV3 in project rest.li by linkedin.
the class DegraderLoadBalancerTest method testWeightedAndLatencyDegradationBalancingRingWithPartitions.
@Test(groups = { "small", "back-end" }, dataProvider = "consistentHashAlgorithms")
public void testWeightedAndLatencyDegradationBalancingRingWithPartitions(String consistentHashAlgorithm) throws URISyntaxException {
DegraderLoadBalancerStrategyV3 strategy = getStrategy(consistentHashAlgorithm);
List<TrackerClient> clientsForPartition0 = new ArrayList<TrackerClient>();
List<TrackerClient> clientsForPartition1 = new ArrayList<TrackerClient>();
URI uri1 = URI.create("http://someTestService/someTestUrl");
URI uri2 = URI.create("http://abcxfweuoeueoueoueoukeueoueoueoueoueouo/2354");
URI uri3 = URI.create("http://slashdot/blah");
URI uri4 = URI.create("http://idle/server");
TestClock clock1 = new TestClock();
TestClock clock2 = new TestClock();
TestClock clock3 = new TestClock();
@SuppressWarnings("serial") TrackerClient client1 = new TrackerClient(uri1, new HashMap<Integer, PartitionData>() {
{
put(0, new PartitionData(1d));
}
}, new TestLoadBalancerClient(uri1), clock1, null);
@SuppressWarnings("serial") TrackerClient client2 = new TrackerClient(uri2, new HashMap<Integer, PartitionData>() {
{
put(0, new PartitionData(0.5d));
put(1, new PartitionData(0.5d));
}
}, new TestLoadBalancerClient(uri2), clock2, null);
@SuppressWarnings("serial") TrackerClient client3 = new TrackerClient(uri3, new HashMap<Integer, PartitionData>() {
{
put(1, new PartitionData(1d));
}
}, new TestLoadBalancerClient(uri3), clock3, null);
final int partitionId0 = 0;
clientsForPartition0.add(client1);
clientsForPartition0.add(client2);
final int partitionId1 = 1;
clientsForPartition1.add(client2);
clientsForPartition1.add(client3);
// force client2 to be disabled
DegraderControl dcClient2Partition0 = client2.getDegraderControl(0);
DegraderControl dcClient2Partition1 = client2.getDegraderControl(1);
dcClient2Partition0.setOverrideMinCallCount(1);
dcClient2Partition0.setMinCallCount(1);
dcClient2Partition0.setMaxDropRate(1d);
dcClient2Partition0.setUpStep(0.4d);
dcClient2Partition0.setHighErrorRate(0);
dcClient2Partition1.setOverrideMinCallCount(1);
dcClient2Partition1.setMinCallCount(1);
dcClient2Partition1.setMaxDropRate(1d);
dcClient2Partition1.setUpStep(0.4d);
dcClient2Partition1.setHighErrorRate(0);
CallCompletion cc = client2.getCallTracker().startCall();
clock2.addMs(1);
cc.endCallWithError();
// force client3 to be disabled
DegraderControl dcClient3Partition1 = client3.getDegraderControl(1);
dcClient3Partition1.setOverrideMinCallCount(1);
dcClient3Partition1.setMinCallCount(1);
dcClient3Partition1.setMaxDropRate(1d);
dcClient3Partition1.setHighErrorRate(0);
dcClient3Partition1.setUpStep(0.2d);
CallCompletion cc3 = client3.getCallTracker().startCall();
clock3.addMs(1);
cc3.endCallWithError();
clock1.addMs(15000);
clock2.addMs(5000);
clock3.addMs(5000);
// trigger a state update
assertNotNull(strategy.getTrackerClient(null, new RequestContext(), 1, partitionId0, clientsForPartition0));
assertNotNull(strategy.getTrackerClient(null, new RequestContext(), 1, partitionId1, clientsForPartition1));
assertNotNull(strategy.getRing(1, partitionId0, clientsForPartition0));
assertNotNull(strategy.getRing(1, partitionId1, clientsForPartition1));
// now do a basic verification to verify getTrackerClient is properly weighting things
int calls = 10000;
int client1Count = 0;
int client2Count = 0;
double tolerance = 0.05d;
for (int i = 0; i < calls; ++i) {
TrackerClient client = strategy.getTrackerClient(null, new RequestContext(), 1, partitionId0, clientsForPartition0);
assertNotNull(client);
if (client.getUri().equals(uri1)) {
++client1Count;
} else {
++client2Count;
}
}
assertTrue(Math.abs((client1Count / (double) calls) - (100 / 130d)) < tolerance);
assertTrue(Math.abs((client2Count / (double) calls) - (30 / 130d)) < tolerance);
client2Count = 0;
int client3Count = 0;
int client4Count = 0;
for (int i = 0; i < calls; ++i) {
TrackerClient client = strategy.getTrackerClient(null, new RequestContext(), 1, partitionId1, clientsForPartition1);
assertNotNull(client);
if (client.getUri().equals(uri3)) {
++client3Count;
} else if (client.getUri().equals(uri2)) {
++client2Count;
} else {
++client4Count;
}
}
assertTrue(Math.abs((client3Count / (double) calls) - (80 / 110d)) < tolerance);
assertTrue(Math.abs((client2Count / (double) calls) - (30 / 110d)) < tolerance);
assertTrue(client4Count == 0);
}
use of com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerStrategyV3 in project rest.li by linkedin.
the class DegraderLoadBalancerTest method testStateIsNotNullAndCallCountIsZero.
@Test(groups = { "small", "back-end" })
public void testStateIsNotNullAndCallCountIsZero() throws URISyntaxException {
DegraderLoadBalancerStrategyV3 strategy = new DegraderLoadBalancerStrategyV3(new DegraderLoadBalancerStrategyConfig(5000), "DegraderLoadBalancerTest", null);
List<TrackerClient> clients = new ArrayList<TrackerClient>();
SettableClock clock1 = new SettableClock();
SettableClock clock2 = new SettableClock();
clients.add(getClient(URI.create("http://test.linkedin.com:3242/fdsaf"), clock1));
clients.add(getClient(URI.create("http://test.linkedin.com:3243/fdsaf"), clock2));
clock1.addDuration(5000);
// this should trigger setting _state (generation id is different) with an override
// of 0d
getTrackerClient(strategy, null, new RequestContext(), 0, clients);
// should not have overridden anything, and default is 0
for (TrackerClient client : clients) {
assertEquals(client.getDegraderControl(DEFAULT_PARTITION_ID).getOverrideDropRate(), 0d);
}
// this should trigger setting _state (state is null and count > 0) with an override
// of 0d
assertNotNull(getTrackerClient(strategy, null, new RequestContext(), -1, clients));
}
use of com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerStrategyV3 in project rest.li by linkedin.
the class DegraderLoadBalancerTest method createRaceCondition.
private List<Runnable> createRaceCondition(final URI uri, Clock clock, final DegraderLoadBalancerStrategyV3 strategy, final CountDownLatch joinLatch) {
final CountDownLatch clientLatch = new CountDownLatch(1);
TrackerClient evilClient = new EvilClient(uri, getDefaultPartitionData(1, 2), new TrackerClientTest.TestClient(), clock, null, clientLatch);
final List<TrackerClient> clients = Collections.singletonList(evilClient);
final Runnable update = new Runnable() {
@Override
public void run() {
// getRing will wait for latch in getPartitionWeight
strategy.getRing(1, 0, clients);
joinLatch.countDown();
}
};
final Runnable resize = new Runnable() {
@Override
public void run() {
// releases latch for partition 0
clientLatch.countDown();
// resize
strategy.getRing(1, 1, clients);
joinLatch.countDown();
}
};
List<Runnable> actions = new ArrayList<Runnable>();
actions.add(update);
actions.add(resize);
return actions;
}
use of com.linkedin.d2.balancer.strategies.degrader.DegraderLoadBalancerStrategyV3 in project rest.li by linkedin.
the class DegraderLoadBalancerTest method testOverrideClusterDropRate.
@Test(groups = { "small", "back-end" })
public void testOverrideClusterDropRate() throws URISyntaxException {
DegraderLoadBalancerStrategyV3 strategy = getStrategy();
List<TrackerClient> clients = new ArrayList<TrackerClient>();
List<TrackerClientUpdater> clientUpdaters = new ArrayList<TrackerClientUpdater>();
for (TrackerClient client : clients) {
clientUpdaters.add(new TrackerClientUpdater(client, DEFAULT_PARTITION_ID));
}
clients.add(getClient(URI.create("http://test.linkedin.com:3242/fdsaf")));
clients.add(getClient(URI.create("http://test.linkedin.com:3243/fdsaf")));
DegraderLoadBalancerStrategyV3.overrideClusterDropRate(DEFAULT_PARTITION_ID, 1d, clientUpdaters);
for (TrackerClientUpdater clientUpdater : clientUpdaters) {
TrackerClient client = clientUpdater.getTrackerClient();
clientUpdater.update();
assertEquals(client.getDegraderControl(DEFAULT_PARTITION_ID).getOverrideDropRate(), 1d);
assertTrue(client.getDegrader(DEFAULT_PARTITION_ID).checkDrop());
}
DegraderLoadBalancerStrategyV3.overrideClusterDropRate(DEFAULT_PARTITION_ID, -1d, clientUpdaters);
// if we don't override, the degrader isn't degraded, so should not drop
for (TrackerClientUpdater clientUpdater : clientUpdaters) {
TrackerClient client = clientUpdater.getTrackerClient();
clientUpdater.update();
assertEquals(client.getDegraderControl(DEFAULT_PARTITION_ID).getOverrideDropRate(), -1d);
assertFalse(client.getDegrader(DEFAULT_PARTITION_ID).checkDrop());
}
DegraderLoadBalancerStrategyV3.overrideClusterDropRate(DEFAULT_PARTITION_ID, 0d, clientUpdaters);
for (TrackerClientUpdater clientUpdater : clientUpdaters) {
TrackerClient client = clientUpdater.getTrackerClient();
clientUpdater.update();
assertEquals(client.getDegraderControl(DEFAULT_PARTITION_ID).getOverrideDropRate(), 0d);
assertFalse(client.getDegrader(DEFAULT_PARTITION_ID).checkDrop());
}
}
Aggregations