Search in sources :

Example 1 with DefaultDarkClusterDispatcher

use of com.linkedin.darkcluster.impl.DefaultDarkClusterDispatcher in project rest.li by linkedin.

the class TestDarkClusterStrategyFactory method setup.

@BeforeMethod
public void setup() {
    _clusterInfoProvider = new MockClusterInfoProvider();
    Facilities facilities = new MockFacilities(_clusterInfoProvider);
    DarkClusterConfig darkClusterConfigOld = createRelativeTrafficMultiplierConfig(0.5f);
    _clusterInfoProvider.addDarkClusterConfig(SOURCE_CLUSTER_NAME, PREEXISTING_DARK_CLUSTER_NAME, darkClusterConfigOld);
    DarkClusterDispatcher darkClusterDispatcher = new DefaultDarkClusterDispatcher(new MockClient(false));
    ClockedExecutor executor = new ClockedExecutor();
    _rateLimiterSupplier = () -> new ConstantQpsRateLimiter(executor, executor, executor, TestConstantQpsDarkClusterStrategy.getBuffer(executor));
    _strategyFactory = new DarkClusterStrategyFactoryImpl(facilities, SOURCE_CLUSTER_NAME, darkClusterDispatcher, new DoNothingNotifier(), new Random(SEED), new CountingVerifierManager(), _rateLimiterSupplier);
    _strategyFactory.start();
}
Also used : DefaultDarkClusterDispatcher(com.linkedin.darkcluster.impl.DefaultDarkClusterDispatcher) DarkClusterDispatcher(com.linkedin.darkcluster.api.DarkClusterDispatcher) DefaultDarkClusterDispatcher(com.linkedin.darkcluster.impl.DefaultDarkClusterDispatcher) ClockedExecutor(com.linkedin.test.util.ClockedExecutor) DarkClusterStrategyFactoryImpl(com.linkedin.darkcluster.impl.DarkClusterStrategyFactoryImpl) Facilities(com.linkedin.d2.balancer.Facilities) ConstantQpsRateLimiter(com.linkedin.r2.transport.http.client.ConstantQpsRateLimiter) Random(java.util.Random) DarkClusterConfig(com.linkedin.d2.DarkClusterConfig) BeforeMethod(org.testng.annotations.BeforeMethod)

Example 2 with DefaultDarkClusterDispatcher

use of com.linkedin.darkcluster.impl.DefaultDarkClusterDispatcher in project rest.li by linkedin.

the class TestDarkClusterFilter method setup.

@BeforeMethod
public void setup() {
    _client = new MockClient(false);
    _darkClusterDispatcher = new DefaultDarkClusterDispatcher(_client);
    _clusterInfoProvider = new SimpleLoadBalancer(new LoadBalancerTestState(), _scheduledExecutorService);
    _facilities = new MockFacilities(_clusterInfoProvider);
    _darkClusterStrategyFactory = new DarkClusterStrategyFactoryImpl(_facilities, SOURCE_CLUSTER_NAME, _darkClusterDispatcher, _notifier, _random, _verifierManager, _rateLimiterSupplier);
    DarkClusterManager darkClusterManager = new DarkClusterManagerImpl(SOURCE_CLUSTER_NAME, _facilities, _darkClusterStrategyFactory, "", "", _notifier);
    _darkClusterFilter = new DarkClusterFilter(darkClusterManager, _verifierManager);
}
Also used : DefaultDarkClusterDispatcher(com.linkedin.darkcluster.impl.DefaultDarkClusterDispatcher) SimpleLoadBalancer(com.linkedin.d2.balancer.simple.SimpleLoadBalancer) DarkClusterFilter(com.linkedin.darkcluster.filter.DarkClusterFilter) DarkClusterManagerImpl(com.linkedin.darkcluster.impl.DarkClusterManagerImpl) LoadBalancerTestState(com.linkedin.d2.balancer.LoadBalancerTestState) DarkClusterManager(com.linkedin.darkcluster.api.DarkClusterManager) DarkClusterStrategyFactoryImpl(com.linkedin.darkcluster.impl.DarkClusterStrategyFactoryImpl) BeforeMethod(org.testng.annotations.BeforeMethod)

Example 3 with DefaultDarkClusterDispatcher

use of com.linkedin.darkcluster.impl.DefaultDarkClusterDispatcher 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");
    });
}
Also used : DefaultDarkClusterDispatcher(com.linkedin.darkcluster.impl.DefaultDarkClusterDispatcher) DarkClusterDispatcher(com.linkedin.darkcluster.api.DarkClusterDispatcher) DefaultDarkClusterDispatcher(com.linkedin.darkcluster.impl.DefaultDarkClusterDispatcher) ArrayList(java.util.ArrayList) ClockedExecutor(com.linkedin.test.util.ClockedExecutor) ConstantQpsRateLimiter(com.linkedin.r2.transport.http.client.ConstantQpsRateLimiter) EvictingCircularBuffer(com.linkedin.r2.transport.http.client.EvictingCircularBuffer) RestRequest(com.linkedin.r2.message.rest.RestRequest) RestRequestBuilder(com.linkedin.r2.message.rest.RestRequestBuilder) RequestContext(com.linkedin.r2.message.RequestContext) ConstantQpsDarkClusterStrategy(com.linkedin.darkcluster.impl.ConstantQpsDarkClusterStrategy) BaseDarkClusterDispatcherImpl(com.linkedin.darkcluster.impl.BaseDarkClusterDispatcherImpl) Test(org.testng.annotations.Test)

Example 4 with DefaultDarkClusterDispatcher

use of com.linkedin.darkcluster.impl.DefaultDarkClusterDispatcher 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");
}
Also used : RelativeTrafficMultiplierDarkClusterStrategy(com.linkedin.darkcluster.impl.RelativeTrafficMultiplierDarkClusterStrategy) DefaultDarkClusterDispatcher(com.linkedin.darkcluster.impl.DefaultDarkClusterDispatcher) DarkClusterDispatcher(com.linkedin.darkcluster.api.DarkClusterDispatcher) DefaultDarkClusterDispatcher(com.linkedin.darkcluster.impl.DefaultDarkClusterDispatcher) RestRequest(com.linkedin.r2.message.rest.RestRequest) Random(java.util.Random) RestRequestBuilder(com.linkedin.r2.message.rest.RestRequestBuilder) RequestContext(com.linkedin.r2.message.RequestContext) BaseDarkClusterDispatcherImpl(com.linkedin.darkcluster.impl.BaseDarkClusterDispatcherImpl) Test(org.testng.annotations.Test)

Example 5 with DefaultDarkClusterDispatcher

use of com.linkedin.darkcluster.impl.DefaultDarkClusterDispatcher 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();
}
Also used : IntStream(java.util.stream.IntStream) DarkClusterStrategy(com.linkedin.darkcluster.api.DarkClusterStrategy) RestRequest(com.linkedin.r2.message.rest.RestRequest) Arrays(java.util.Arrays) DataProvider(org.testng.annotations.DataProvider) IdenticalTrafficMultiplierDarkClusterStrategy(com.linkedin.darkcluster.impl.IdenticalTrafficMultiplierDarkClusterStrategy) RestRequestBuilder(com.linkedin.r2.message.rest.RestRequestBuilder) Random(java.util.Random) Test(org.testng.annotations.Test) Collectors(java.util.stream.Collectors) Mockito(org.mockito.Mockito) BaseDarkClusterDispatcherImpl(com.linkedin.darkcluster.impl.BaseDarkClusterDispatcherImpl) List(java.util.List) RequestContext(com.linkedin.r2.message.RequestContext) Assert(org.testng.Assert) DarkClusterDispatcher(com.linkedin.darkcluster.api.DarkClusterDispatcher) URI(java.net.URI) DefaultDarkClusterDispatcher(com.linkedin.darkcluster.impl.DefaultDarkClusterDispatcher) DefaultDarkClusterDispatcher(com.linkedin.darkcluster.impl.DefaultDarkClusterDispatcher) IdenticalTrafficMultiplierDarkClusterStrategy(com.linkedin.darkcluster.impl.IdenticalTrafficMultiplierDarkClusterStrategy) DarkClusterDispatcher(com.linkedin.darkcluster.api.DarkClusterDispatcher) DefaultDarkClusterDispatcher(com.linkedin.darkcluster.impl.DefaultDarkClusterDispatcher) DarkClusterStrategy(com.linkedin.darkcluster.api.DarkClusterStrategy) IdenticalTrafficMultiplierDarkClusterStrategy(com.linkedin.darkcluster.impl.IdenticalTrafficMultiplierDarkClusterStrategy) RestRequest(com.linkedin.r2.message.rest.RestRequest) Random(java.util.Random) RestRequestBuilder(com.linkedin.r2.message.rest.RestRequestBuilder) RequestContext(com.linkedin.r2.message.RequestContext) BaseDarkClusterDispatcherImpl(com.linkedin.darkcluster.impl.BaseDarkClusterDispatcherImpl) Test(org.testng.annotations.Test)

Aggregations

DefaultDarkClusterDispatcher (com.linkedin.darkcluster.impl.DefaultDarkClusterDispatcher)6 DarkClusterDispatcher (com.linkedin.darkcluster.api.DarkClusterDispatcher)5 BaseDarkClusterDispatcherImpl (com.linkedin.darkcluster.impl.BaseDarkClusterDispatcherImpl)4 RequestContext (com.linkedin.r2.message.RequestContext)4 RestRequest (com.linkedin.r2.message.rest.RestRequest)4 RestRequestBuilder (com.linkedin.r2.message.rest.RestRequestBuilder)4 Test (org.testng.annotations.Test)4 Random (java.util.Random)3 DarkClusterStrategyFactoryImpl (com.linkedin.darkcluster.impl.DarkClusterStrategyFactoryImpl)2 ConstantQpsRateLimiter (com.linkedin.r2.transport.http.client.ConstantQpsRateLimiter)2 ClockedExecutor (com.linkedin.test.util.ClockedExecutor)2 BeforeMethod (org.testng.annotations.BeforeMethod)2 DarkClusterConfig (com.linkedin.d2.DarkClusterConfig)1 Facilities (com.linkedin.d2.balancer.Facilities)1 LoadBalancerTestState (com.linkedin.d2.balancer.LoadBalancerTestState)1 SimpleLoadBalancer (com.linkedin.d2.balancer.simple.SimpleLoadBalancer)1 DarkClusterManager (com.linkedin.darkcluster.api.DarkClusterManager)1 DarkClusterStrategy (com.linkedin.darkcluster.api.DarkClusterStrategy)1 DarkClusterFilter (com.linkedin.darkcluster.filter.DarkClusterFilter)1 ConstantQpsDarkClusterStrategy (com.linkedin.darkcluster.impl.ConstantQpsDarkClusterStrategy)1