use of com.linkedin.darkcluster.impl.BaseDarkClusterDispatcherImpl in project rest.li by linkedin.
the class TestConstantQpsDarkClusterStrategy method testStrategy.
@Test(dataProvider = "qpsKeys")
public void testStrategy(int duration, float inboundQps, float outboundQps, int numSourceInstances, int numDarkInstances) {
IntStream.of(1, 1000, 1000000).forEach(capacity -> {
DarkClusterDispatcher darkClusterDispatcher = new DefaultDarkClusterDispatcher(new MockClient(false));
ClockedExecutor executor = new ClockedExecutor();
Supplier<ConstantQpsRateLimiter> uniqueRateLimiterSupplier = () -> {
EvictingCircularBuffer uniqueBuffer = TestConstantQpsDarkClusterStrategy.getBuffer(executor);
ConstantQpsRateLimiter limiter = new ConstantQpsRateLimiter(executor, executor, executor, uniqueBuffer);
limiter.setBufferCapacity(capacity);
limiter.setBufferTtl(Integer.MAX_VALUE, ChronoUnit.DAYS);
return limiter;
};
ConstantQpsRateLimiter sharedRateLimiter = uniqueRateLimiterSupplier.get();
Supplier<ConstantQpsRateLimiter> sharedRateLimiterSupplier = () -> sharedRateLimiter;
MockClusterInfoProvider mockClusterInfoProvider = new MockClusterInfoProvider();
mockClusterInfoProvider.putHttpsClusterCount(SOURCE_CLUSTER_NAME, numSourceInstances);
// dark cluster 1
BaseDarkClusterDispatcherImpl baseDispatcherOne = new BaseDarkClusterDispatcherImpl(DARK_CLUSTER_NAME_ONE, darkClusterDispatcher, new DoNothingNotifier(), new CountingVerifierManager());
mockClusterInfoProvider.putHttpsClusterCount(DARK_CLUSTER_NAME_ONE, numDarkInstances);
ConstantQpsRateLimiter rateLimiterOne = sharedRateLimiterSupplier.get();
// dark cluster 2
BaseDarkClusterDispatcherImpl baseDispatcherTwo = new BaseDarkClusterDispatcherImpl(DARK_CLUSTER_NAME_TWO, darkClusterDispatcher, new DoNothingNotifier(), new CountingVerifierManager());
mockClusterInfoProvider.putHttpsClusterCount(DARK_CLUSTER_NAME_TWO, numDarkInstances);
ConstantQpsRateLimiter rateLimiterTwo = sharedRateLimiterSupplier.get();
// dark cluster 3
BaseDarkClusterDispatcherImpl baseDispatcherThree = new BaseDarkClusterDispatcherImpl(DARK_CLUSTER_NAME_THREE, darkClusterDispatcher, new DoNothingNotifier(), new CountingVerifierManager());
mockClusterInfoProvider.putHttpsClusterCount(DARK_CLUSTER_NAME_THREE, numDarkInstances);
ConstantQpsRateLimiter rateLimiterThree = uniqueRateLimiterSupplier.get();
List<ConstantQpsDarkClusterStrategy> strategies = new ArrayList<>();
strategies.add(new ConstantQpsDarkClusterStrategy(SOURCE_CLUSTER_NAME, DARK_CLUSTER_NAME_ONE, outboundQps, baseDispatcherOne, new DoNothingNotifier(), mockClusterInfoProvider, rateLimiterOne));
strategies.add(new ConstantQpsDarkClusterStrategy(SOURCE_CLUSTER_NAME, DARK_CLUSTER_NAME_TWO, outboundQps, baseDispatcherTwo, new DoNothingNotifier(), mockClusterInfoProvider, rateLimiterTwo));
strategies.add(new ConstantQpsDarkClusterStrategy(SOURCE_CLUSTER_NAME, DARK_CLUSTER_NAME_THREE, outboundQps, baseDispatcherThree, new DoNothingNotifier(), mockClusterInfoProvider, rateLimiterThree));
// simulate receiving the configured qps while dispatching over the duration
int msBetweenEachInboundRequest = (int) (1000 / inboundQps);
for (int runTime = 0; runTime < duration; runTime = runTime + msBetweenEachInboundRequest) {
RestRequest dummyRestRequest = new RestRequestBuilder(URI.create("foo")).build();
for (ConstantQpsDarkClusterStrategy strategy : strategies) {
strategy.handleRequest(dummyRestRequest, dummyRestRequest, new RequestContext());
}
executor.runFor(msBetweenEachInboundRequest);
}
double validation = ((duration == 0 ? 0 : duration / 1000.0) * outboundQps * numDarkInstances) / (double) (numSourceInstances);
// Cluster One and Two share a rate limiter, so their combined QPS should match the expected value.
int actualCountClusterOne = baseDispatcherOne.getRequestCount();
int actualCountClusterTwo = baseDispatcherTwo.getRequestCount();
int expectedCountClusterOneAndTwo = (int) validation;
Assert.assertEquals(actualCountClusterOne + actualCountClusterTwo, expectedCountClusterOneAndTwo, expectedCountClusterOneAndTwo * ERR_PCT, "count not within expected range");
// Cluster Three uses its own so it matches the expected value on its own.
int expectedCountClusterThree = (int) validation;
int actualCountClusterThree = baseDispatcherThree.getRequestCount();
Assert.assertEquals(actualCountClusterThree, expectedCountClusterThree, expectedCountClusterThree * ERR_PCT, "count not within expected range");
});
}
use of com.linkedin.darkcluster.impl.BaseDarkClusterDispatcherImpl in project rest.li by linkedin.
the class TestRelativeTrafficMultiplierDarkClusterStrategy method testStrategy.
@Test(dataProvider = "multiplierKeys")
public void testStrategy(int numIterations, float multiplier, int numSourceInstances, int numDarkInstances) {
DarkClusterDispatcher darkClusterDispatcher = new DefaultDarkClusterDispatcher(new MockClient(false));
BaseDarkClusterDispatcherImpl baseDispatcher = new BaseDarkClusterDispatcherImpl(DARK_CLUSTER_NAME, darkClusterDispatcher, new DoNothingNotifier(), new CountingVerifierManager());
MockClusterInfoProvider mockClusterInfoProvider = new MockClusterInfoProvider();
mockClusterInfoProvider.putHttpsClusterCount(DARK_CLUSTER_NAME, numDarkInstances);
mockClusterInfoProvider.putHttpsClusterCount(SOURCE_CLUSTER_NAME, numSourceInstances);
RelativeTrafficMultiplierDarkClusterStrategy strategy = new RelativeTrafficMultiplierDarkClusterStrategy(SOURCE_CLUSTER_NAME, DARK_CLUSTER_NAME, multiplier, baseDispatcher, new DoNothingNotifier(), mockClusterInfoProvider, new Random(SEED));
for (int i = 0; i < numIterations; i++) {
RestRequest dummyRestRequest = new RestRequestBuilder(URI.create("foo")).build();
strategy.handleRequest(dummyRestRequest, dummyRestRequest, new RequestContext());
}
int expectedCount = (int) (numIterations * multiplier * numDarkInstances) / (numSourceInstances);
int actualCount = baseDispatcher.getRequestCount();
Assert.assertEquals(actualCount, expectedCount, expectedCount * ERR_PCT, "count not within expected range");
}
use of com.linkedin.darkcluster.impl.BaseDarkClusterDispatcherImpl in project rest.li by linkedin.
the class TestIdenticalTrafficMultiplierDarkClusterStrategy method testHandleRequest.
@Test(dataProvider = "getDarkClusters")
public void testHandleRequest(List<DarkClusterMetadata> darkClusterMetadataList, float expectedRandomNumber) {
String sourceClusterName = "sourceCluster";
DarkClusterDispatcher darkClusterDispatcher = new DefaultDarkClusterDispatcher(new MockClient(false));
Random random = Mockito.mock(Random.class);
Mockito.when(random.nextFloat()).thenReturn(expectedRandomNumber);
List<IdenticalTrafficMultiplierDarkClusterStrategy> strategies = darkClusterMetadataList.stream().map(darkClusterMetadata -> {
BaseDarkClusterDispatcherImpl baseDispatcher = new BaseDarkClusterDispatcherImpl(darkClusterMetadata._darkClusterName, darkClusterDispatcher, new DoNothingNotifier(), new CountingVerifierManager());
MockClusterInfoProvider mockClusterInfoProvider = new MockClusterInfoProvider();
mockClusterInfoProvider.putHttpsClusterCount(darkClusterMetadata._darkClusterName, 1);
mockClusterInfoProvider.putHttpsClusterCount(sourceClusterName, 1);
return new IdenticalTrafficMultiplierDarkClusterStrategy(sourceClusterName, darkClusterMetadata._darkClusterName, darkClusterMetadata._multiplier, baseDispatcher, new DoNothingNotifier(), mockClusterInfoProvider, random);
}).collect(Collectors.toList());
RestRequest dummyRestRequest = new RestRequestBuilder(URI.create("foo")).build();
RestRequest dummyDarkRequest = new RestRequestBuilder(URI.create("darkfoo")).build();
RequestContext dummyRequestContext = new RequestContext();
IntStream.range(0, darkClusterMetadataList.size()).forEach(index -> {
DarkClusterMetadata darkClusterMetadata = darkClusterMetadataList.get(index);
DarkClusterStrategy strategy = strategies.get(index);
boolean darkRequestSent = strategy.handleRequest(dummyRestRequest, dummyDarkRequest, dummyRequestContext);
Assert.assertEquals(darkRequestSent, darkClusterMetadata._darkRequestSent);
});
Assert.assertEquals(dummyRequestContext.getLocalAttr("identicalTrafficMultiplier.randomNumber"), expectedRandomNumber);
Mockito.verify(random).nextFloat();
}
use of com.linkedin.darkcluster.impl.BaseDarkClusterDispatcherImpl in project rest.li by linkedin.
the class TestBaseDarkClusterDispatcher method testBaseDispatcher.
@Test(dataProvider = "provideKeys")
public void testBaseDispatcher(int numDuplicates, boolean failRequests, boolean requestSent, int expectedSuccessCount, int expectedRequestCount, int expectedExceptionCount) {
DarkClusterDispatcher darkClusterDispatcher = new DefaultDarkClusterDispatcher(new MockClient(failRequests));
BaseDarkClusterDispatcherImpl baseDispatcher = new BaseDarkClusterDispatcherImpl(DARK_CLUSTER_NAME, darkClusterDispatcher, new DoNothingNotifier(), new CountingVerifierManager());
RestRequest dummyRestRequest = new RestRequestBuilder(URI.create("foo")).build();
boolean result = baseDispatcher.sendRequest(dummyRestRequest, dummyRestRequest, new RequestContext(), numDuplicates);
Assert.assertEquals(result, requestSent, "expected: " + requestSent);
Assert.assertEquals(baseDispatcher.getSuccessCount(), expectedSuccessCount, "unexpected successCount");
Assert.assertEquals(baseDispatcher.getRequestCount(), expectedRequestCount, "unexpected requestCount");
Assert.assertEquals(baseDispatcher.getExceptionCount(), expectedExceptionCount, "unexpected exceptionCount");
}
Aggregations