use of com.linkedin.d2.DarkClusterConfig in project rest.li by linkedin.
the class TestDarkClusterStrategyFactory method testStrategyZeroMultiplier.
@Test
public void testStrategyZeroMultiplier() {
DarkClusterConfig darkClusterConfig1 = createRelativeTrafficMultiplierConfig(0f);
DarkClusterStrategyNameArray darkClusterStrategyList = new DarkClusterStrategyNameArray();
darkClusterStrategyList.addAll(Collections.singletonList(RELATIVE_TRAFFIC));
darkClusterConfig1.setDarkClusterStrategyPrioritizedList(darkClusterStrategyList);
_clusterInfoProvider.addDarkClusterConfig(SOURCE_CLUSTER_NAME, DARK_CLUSTER_NAME, darkClusterConfig1);
DarkClusterStrategy strategy = _strategyFactory.get(DARK_CLUSTER_NAME);
// test that we choose a NoOpDarkClusterStrategy because we want to allow RelativeTrafficMultiplierStrategy with a zero muliplier to be
// a NoOp. This allows clients to easily turn off traffic without adjusting multiple values.
Assert.assertTrue(strategy instanceof NoOpDarkClusterStrategy);
}
use of com.linkedin.d2.DarkClusterConfig in project rest.li by linkedin.
the class TestDarkClusterStrategyFactory method testNoChangeStrategyOnNotification.
@Test
public void testNoChangeStrategyOnNotification() {
DarkClusterConfig darkClusterConfig1 = createRelativeTrafficMultiplierConfig(0.5f);
DarkClusterConfig darkClusterConfig2 = createRelativeTrafficMultiplierConfig(1.0f);
_clusterInfoProvider.addDarkClusterConfig(SOURCE_CLUSTER_NAME, DARK_CLUSTER_NAME, darkClusterConfig1);
_clusterInfoProvider.notifyListenersClusterAdded(SOURCE_CLUSTER_NAME);
DarkClusterStrategy strategy = _strategyFactory.get(DARK_CLUSTER_NAME);
Assert.assertTrue(strategy instanceof RelativeTrafficMultiplierDarkClusterStrategy);
Assert.assertEquals(((RelativeTrafficMultiplierDarkClusterStrategy) strategy).getMultiplier(), 0.5f, "expected 0.5f multiplier");
// update Strategy, then simulating a notification on the dark cluster.
_clusterInfoProvider.addDarkClusterConfig(SOURCE_CLUSTER_NAME, DARK_CLUSTER_NAME, darkClusterConfig2);
_clusterInfoProvider.notifyListenersClusterAdded(DARK_CLUSTER_NAME);
// Nothing should have been changed, since we should be ignoring dark cluster changes. (strategy-impacting changes are all captured
// in the source cluster data)
DarkClusterStrategy strategy2 = _strategyFactory.get(DARK_CLUSTER_NAME);
Assert.assertTrue(strategy2 instanceof RelativeTrafficMultiplierDarkClusterStrategy);
Assert.assertEquals(((RelativeTrafficMultiplierDarkClusterStrategy) strategy2).getMultiplier(), 0.5f, "expected 0.5f multiplier");
}
use of com.linkedin.d2.DarkClusterConfig in project rest.li by linkedin.
the class TestDarkClusterStrategyFactory method testStrategyRaceCondition.
@Test
public void testStrategyRaceCondition() {
int noopStrategyCount = 0;
DarkClusterConfig darkClusterConfig1 = createRelativeTrafficMultiplierConfig(0.5f);
_clusterInfoProvider.addDarkClusterConfig(SOURCE_CLUSTER_NAME, DARK_CLUSTER_NAME, darkClusterConfig1);
_clusterInfoProvider.notifyListenersClusterAdded(SOURCE_CLUSTER_NAME);
DarkClusterStrategy strategy = _strategyFactory.get(DARK_CLUSTER_NAME);
Assert.assertTrue(strategy instanceof RelativeTrafficMultiplierDarkClusterStrategy);
Assert.assertEquals(((RelativeTrafficMultiplierDarkClusterStrategy) strategy).getMultiplier(), 0.5f, "expected 0.5f multiplier");
// this was registered after DarkClusterStrategyFactoryImpl registered it's clusterListener.
_clusterInfoProvider.registerClusterListener(new DeletingClusterListener(_clusterInfoProvider));
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
final CountDownLatch latch = new CountDownLatch(1);
try {
scheduledExecutorService.scheduleAtFixedRate(() -> {
_clusterInfoProvider.notifyListenersClusterAdded(SOURCE_CLUSTER_NAME);
latch.countDown();
}, 0, 1, TimeUnit.MILLISECONDS);
if (!latch.await(30, TimeUnit.SECONDS)) {
fail("unable to execute task on executor");
}
for (int i = 0; i < 100000; i++) {
strategy = _strategyFactory.get(DARK_CLUSTER_NAME);
// verified that this will catch race conditions, saw it happen 9/100k times.
Assert.assertNotNull(strategy, "null at iteration: " + i);
if (strategy instanceof NoOpDarkClusterStrategy) {
noopStrategyCount++;
}
}
System.out.println("noopStrategyCount: " + noopStrategyCount);
} catch (InterruptedException ie) {
fail("got interrupted exception", ie);
} finally {
scheduledExecutorService.shutdown();
}
}
use of com.linkedin.d2.DarkClusterConfig in project rest.li by linkedin.
the class TestDarkClusterManager method testBasic.
@Test(dataProvider = "provideKeys")
public void testBasic(String whitelist, String blacklist, String httpMethod, DarkGateKeeper darkGateKeeper, int expectedWhiteCount, int expectedBlackCount) {
MockClusterInfoProvider clusterInfoProvider = new MockClusterInfoProvider();
Facilities facilities = new MockFacilities(clusterInfoProvider);
MockStrategyFactory strategyFactory = new MockStrategyFactory();
DarkClusterManager darkClusterManager = new DarkClusterManagerImpl(SOURCE_CLUSTER_NAME, facilities, strategyFactory, whitelist, blacklist, new DoNothingNotifier(), darkGateKeeper);
strategyFactory.start();
// This configuration will choose the RelativeTrafficMultiplierDarkClusterStrategy
DarkClusterConfig darkClusterConfig = createRelativeTrafficMultiplierConfig(1.0f);
clusterInfoProvider.addDarkClusterConfig(SOURCE_CLUSTER_NAME, DARK_CLUSTER_NAME, darkClusterConfig);
RestRequest restRequest1 = new RestRequestBuilder(URI.create("/white")).setMethod(httpMethod).build();
boolean whiteStatus = darkClusterManager.handleDarkRequest(restRequest1, new RequestContext());
RestRequest restRequest2 = new RestRequestBuilder(URI.create("/black")).setMethod(httpMethod).build();
boolean blackStatus = darkClusterManager.handleDarkRequest(restRequest2, new RequestContext());
Assert.assertEquals(whiteStatus, expectedWhiteCount > 0, "white uri requests not as expected");
Assert.assertEquals(blackStatus, expectedBlackCount > 0, "black uri requests not as expected");
Assert.assertEquals(strategyFactory.strategyGetOrCreateCount, expectedWhiteCount + expectedBlackCount, "unexpected strategy GetOrCreateCount");
}
use of com.linkedin.d2.DarkClusterConfig in project rest.li by linkedin.
the class TestDarkClusterFilter method testDarkClusterAssemblyWithDarkCluster.
@Test
public void testDarkClusterAssemblyWithDarkCluster() {
// we need to have a Mock clusterInfoProvider in order to set up a dark cluster.
MockClusterInfoProvider clusterInfoProvider = new MockClusterInfoProvider();
_facilities = new MockFacilities(clusterInfoProvider);
_darkClusterStrategyFactory = new DarkClusterStrategyFactoryImpl(_facilities, SOURCE_CLUSTER_NAME, _darkClusterDispatcher, _notifier, _random, _verifierManager, _rateLimiterSupplier);
_darkClusterStrategyFactory.start();
DarkClusterManager darkClusterManager = new DarkClusterManagerImpl(SOURCE_CLUSTER_NAME, _facilities, _darkClusterStrategyFactory, "", "", _notifier);
_darkClusterFilter = new DarkClusterFilter(darkClusterManager, _verifierManager);
// set the multiplier to 1 so that traffic gets sent.
DarkClusterConfig darkClusterConfig = createRelativeTrafficMultiplierConfig(1.0f);
clusterInfoProvider.addDarkClusterConfig(SOURCE_CLUSTER_NAME, DARK_CLUSTER_NAME, darkClusterConfig);
clusterInfoProvider.notifyListenersClusterAdded(SOURCE_CLUSTER_NAME);
// send the request, expecting it to make it all the way down to the client
RestRequest restRequest = new RestRequestBuilder(URI.create("foo")).build();
_darkClusterFilter.onRestRequest(restRequest, new RequestContext(), new HashMap<>(), new DummyNextFilter());
Assert.assertEquals(_client.requestAuthorityMap.size(), 1, "expected 1 request to be sent");
_darkClusterFilter.onRestError(new RuntimeException("test"), new RequestContext(), new HashMap<>(), new DummyNextFilter());
_darkClusterFilter.onRestResponse(new RestResponseBuilder().build(), new RequestContext(), new HashMap<>(), new DummyNextFilter());
}
Aggregations