Search in sources :

Example 6 with DarkClusterStrategyNameArray

use of com.linkedin.d2.DarkClusterStrategyNameArray 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);
}
Also used : DarkClusterStrategyNameArray(com.linkedin.d2.DarkClusterStrategyNameArray) DarkClusterConfig(com.linkedin.d2.DarkClusterConfig) NoOpDarkClusterStrategy(com.linkedin.darkcluster.api.NoOpDarkClusterStrategy) RelativeTrafficMultiplierDarkClusterStrategy(com.linkedin.darkcluster.impl.RelativeTrafficMultiplierDarkClusterStrategy) DarkClusterStrategy(com.linkedin.darkcluster.api.DarkClusterStrategy) NoOpDarkClusterStrategy(com.linkedin.darkcluster.api.NoOpDarkClusterStrategy) Test(org.testng.annotations.Test)

Example 7 with DarkClusterStrategyNameArray

use of com.linkedin.d2.DarkClusterStrategyNameArray in project rest.li by linkedin.

the class DarkClusterStrategyFactoryImpl method createStrategy.

/**
 * In the future, additional strategies can be added, and the logic here can choose the appropriate one based on the config values.
 */
private DarkClusterStrategy createStrategy(String darkClusterName, DarkClusterConfig darkClusterConfig) {
    if (darkClusterConfig.hasDarkClusterStrategyPrioritizedList()) {
        DarkClusterStrategyNameArray strategyList = darkClusterConfig.getDarkClusterStrategyPrioritizedList();
        for (com.linkedin.d2.DarkClusterStrategyName darkClusterStrategyName : strategyList) {
            switch(darkClusterStrategyName) {
                case RELATIVE_TRAFFIC:
                    if (RelativeTrafficMultiplierDarkClusterStrategy.isValidConfig(darkClusterConfig)) {
                        BaseDarkClusterDispatcher baseDarkClusterDispatcher = new BaseDarkClusterDispatcherImpl(darkClusterName, _darkClusterDispatcher, _notifier, _verifierManager);
                        return new RelativeTrafficMultiplierDarkClusterStrategy(_sourceClusterName, darkClusterName, darkClusterConfig.getMultiplier(), baseDarkClusterDispatcher, _notifier, _facilities.getClusterInfoProvider(), _random);
                    }
                    break;
                case IDENTICAL_TRAFFIC:
                    if (IdenticalTrafficMultiplierDarkClusterStrategy.isValidConfig(darkClusterConfig)) {
                        BaseDarkClusterDispatcher baseDarkClusterDispatcher = new BaseDarkClusterDispatcherImpl(darkClusterName, _darkClusterDispatcher, _notifier, _verifierManager);
                        return new IdenticalTrafficMultiplierDarkClusterStrategy(_sourceClusterName, darkClusterName, darkClusterConfig.getMultiplier(), baseDarkClusterDispatcher, _notifier, _facilities.getClusterInfoProvider(), _random);
                    }
                    break;
                case CONSTANT_QPS:
                    if (_rateLimiterSupplier == null) {
                        LOG.error("Dark Cluster {} configured to use CONSTANT_QPS strategy, but no rate limiter provided during instantiation. " + "No Dark Cluster strategy will be used!", darkClusterName);
                        break;
                    }
                    if (ConstantQpsDarkClusterStrategy.isValidConfig(darkClusterConfig)) {
                        BaseDarkClusterDispatcher baseDarkClusterDispatcher = new BaseDarkClusterDispatcherImpl(darkClusterName, _darkClusterDispatcher, _notifier, _verifierManager);
                        ConstantQpsRateLimiter rateLimiter = _rateLimiterSupplier.get();
                        rateLimiter.setBufferCapacity(darkClusterConfig.getDispatcherMaxRequestsToBuffer());
                        rateLimiter.setBufferTtl(darkClusterConfig.getDispatcherBufferedRequestExpiryInSeconds(), ChronoUnit.SECONDS);
                        return new ConstantQpsDarkClusterStrategy(_sourceClusterName, darkClusterName, darkClusterConfig.getDispatcherOutboundTargetRate(), baseDarkClusterDispatcher, _notifier, _facilities.getClusterInfoProvider(), rateLimiter);
                    }
                    break;
                default:
                    break;
            }
        }
    }
    return new NoOpDarkClusterStrategy();
}
Also used : ConstantQpsRateLimiter(com.linkedin.r2.transport.http.client.ConstantQpsRateLimiter) DarkClusterStrategyNameArray(com.linkedin.d2.DarkClusterStrategyNameArray) BaseDarkClusterDispatcher(com.linkedin.darkcluster.api.BaseDarkClusterDispatcher) NoOpDarkClusterStrategy(com.linkedin.darkcluster.api.NoOpDarkClusterStrategy)

Example 8 with DarkClusterStrategyNameArray

use of com.linkedin.d2.DarkClusterStrategyNameArray in project rest.li by linkedin.

the class DarkClustersConverter method toConfig.

public static DarkClusterConfigMap toConfig(Map<String, Object> properties) {
    DarkClusterConfigMap configMap = new DarkClusterConfigMap();
    for (Map.Entry<String, Object> entry : properties.entrySet()) {
        String darkClusterName = entry.getKey();
        DarkClusterConfig darkClusterConfig = new DarkClusterConfig();
        @SuppressWarnings("unchecked") Map<String, Object> props = (Map<String, Object>) entry.getValue();
        if (props.containsKey(PropertyKeys.DARK_CLUSTER_MULTIPLIER)) {
            darkClusterConfig.setMultiplier(PropertyUtil.coerce(props.get(PropertyKeys.DARK_CLUSTER_MULTIPLIER), Float.class));
        } else {
            // to maintain backwards compatibility with previously ser/de, set the default on deserialization
            darkClusterConfig.setMultiplier(DARK_CLUSTER_DEFAULT_MULTIPLIER);
        }
        if (props.containsKey(PropertyKeys.DARK_CLUSTER_OUTBOUND_TARGET_RATE)) {
            darkClusterConfig.setDispatcherOutboundTargetRate(PropertyUtil.coerce(props.get(PropertyKeys.DARK_CLUSTER_OUTBOUND_TARGET_RATE), Float.class));
        } else {
            darkClusterConfig.setDispatcherOutboundTargetRate(DARK_CLUSTER_DEFAULT_TARGET_RATE);
        }
        if (props.containsKey(PropertyKeys.DARK_CLUSTER_MAX_REQUESTS_TO_BUFFER)) {
            darkClusterConfig.setDispatcherMaxRequestsToBuffer(PropertyUtil.coerce(props.get(PropertyKeys.DARK_CLUSTER_MAX_REQUESTS_TO_BUFFER), Integer.class));
        } else {
            darkClusterConfig.setDispatcherMaxRequestsToBuffer(DARK_CLUSTER_DEFAULT_MAX_REQUESTS_TO_BUFFER);
        }
        if (props.containsKey(PropertyKeys.DARK_CLUSTER_BUFFERED_REQUEST_EXPIRY_IN_SECONDS)) {
            darkClusterConfig.setDispatcherBufferedRequestExpiryInSeconds(PropertyUtil.coerce(props.get(PropertyKeys.DARK_CLUSTER_BUFFERED_REQUEST_EXPIRY_IN_SECONDS), Integer.class));
        } else {
            darkClusterConfig.setDispatcherBufferedRequestExpiryInSeconds(DARK_CLUSTER_DEFAULT_BUFFERED_REQUEST_EXPIRY_IN_SECONDS);
        }
        if (props.containsKey(PropertyKeys.DARK_CLUSTER_STRATEGY_LIST)) {
            DataList dataList = new DataList();
            @SuppressWarnings("unchecked") List<String> strategyList = (List<String>) props.get(PropertyKeys.DARK_CLUSTER_STRATEGY_LIST);
            dataList.addAll(strategyList);
            DarkClusterStrategyNameArray darkClusterStrategyNameArray = new DarkClusterStrategyNameArray(dataList);
            darkClusterConfig.setDarkClusterStrategyPrioritizedList(darkClusterStrategyNameArray);
        }
        if (props.containsKey(PropertyKeys.DARK_CLUSTER_TRANSPORT_CLIENT_PROPERTIES)) {
            @SuppressWarnings("unchecked") D2TransportClientProperties transportClientProperties = TransportClientPropertiesConverter.toConfig((Map<String, Object>) props.get(PropertyKeys.DARK_CLUSTER_TRANSPORT_CLIENT_PROPERTIES));
            darkClusterConfig.setTransportClientProperties(transportClientProperties);
        }
        configMap.put(darkClusterName, darkClusterConfig);
    }
    return configMap;
}
Also used : DarkClusterStrategyNameArray(com.linkedin.d2.DarkClusterStrategyNameArray) D2TransportClientProperties(com.linkedin.d2.D2TransportClientProperties) DarkClusterConfigMap(com.linkedin.d2.DarkClusterConfigMap) DataList(com.linkedin.data.DataList) DarkClusterConfig(com.linkedin.d2.DarkClusterConfig) DataList(com.linkedin.data.DataList) ArrayList(java.util.ArrayList) List(java.util.List) DarkClusterConfigMap(com.linkedin.d2.DarkClusterConfigMap) HashMap(java.util.HashMap) Map(java.util.Map)

Example 9 with DarkClusterStrategyNameArray

use of com.linkedin.d2.DarkClusterStrategyNameArray in project rest.li by linkedin.

the class DarkClustersConverterTest method testBadStrategies.

@Test
public void testBadStrategies() {
    Map<String, Object> props = new HashMap<>();
    List<String> myStrategyList = new ArrayList<>();
    myStrategyList.add("RELATIVE_TRAFFIC");
    myStrategyList.add("BLAH_BLAH");
    Map<String, Object> darkClusterMap = new HashMap<>();
    darkClusterMap.put(PropertyKeys.DARK_CLUSTER_STRATEGY_LIST, myStrategyList);
    props.put(DARK_CLUSTER_KEY, darkClusterMap);
    DarkClusterConfigMap configMap = DarkClustersConverter.toConfig(props);
    DarkClusterStrategyNameArray strategyList = configMap.get(DARK_CLUSTER_KEY).getDarkClusterStrategyPrioritizedList();
    Assert.assertEquals(strategyList.get(0), DarkClusterStrategyName.RELATIVE_TRAFFIC, "first strategy should be RELATIVE_TRAFFIC");
    // the bad strategy BLAH_BLAH gets converted to unknown on access
    Assert.assertEquals(strategyList.get(1), DarkClusterStrategyName.$UNKNOWN, "second strategy should be unknown");
}
Also used : DarkClusterConfigMap(com.linkedin.d2.DarkClusterConfigMap) HashMap(java.util.HashMap) DarkClusterStrategyNameArray(com.linkedin.d2.DarkClusterStrategyNameArray) ArrayList(java.util.ArrayList) Test(org.testng.annotations.Test)

Example 10 with DarkClusterStrategyNameArray

use of com.linkedin.d2.DarkClusterStrategyNameArray in project rest.li by linkedin.

the class DarkClustersConverterTest method testEntriesInClusterConfig.

@Test
public void testEntriesInClusterConfig() {
    DarkClusterConfigMap configMap = new DarkClusterConfigMap();
    DarkClusterStrategyNameArray multiplierStrategyTypeArray = new DarkClusterStrategyNameArray();
    multiplierStrategyTypeArray.add(DarkClusterStrategyName.RELATIVE_TRAFFIC.RELATIVE_TRAFFIC);
    D2TransportClientProperties transportClientProperties = new D2TransportClientProperties().setRequestTimeout(1000);
    DarkClusterConfig config = new DarkClusterConfig().setDarkClusterStrategyPrioritizedList(multiplierStrategyTypeArray).setTransportClientProperties(transportClientProperties);
    configMap.put(DARK_CLUSTER_KEY, config);
    DarkClusterConfigMap expectedConfigMap = new DarkClusterConfigMap();
    DarkClusterConfig expectedConfig = new DarkClusterConfig(config.data());
    expectedConfig.setMultiplier(0);
    expectedConfig.setDispatcherOutboundTargetRate(0);
    expectedConfig.setDispatcherMaxRequestsToBuffer(1);
    expectedConfig.setDispatcherBufferedRequestExpiryInSeconds(1);
    expectedConfigMap.put(DARK_CLUSTER_KEY, expectedConfig);
    DarkClusterConfigMap resultConfigMap = DarkClustersConverter.toConfig(DarkClustersConverter.toProperties(configMap));
    Assert.assertEquals(resultConfigMap, expectedConfigMap);
    // verify values are converted properly.
    DarkClusterConfig darkClusterConfig = resultConfigMap.get(DARK_CLUSTER_KEY);
    Assert.assertEquals(darkClusterConfig.getMultiplier(), DARK_CLUSTER_DEFAULT_MULTIPLIER, "unexpected multiplier");
    Assert.assertEquals(darkClusterConfig.getDarkClusterStrategyPrioritizedList().size(), 1, "there should be one strategy");
    Assert.assertEquals(darkClusterConfig.getDarkClusterStrategyPrioritizedList().get(0), DarkClusterStrategyName.RELATIVE_TRAFFIC, "expected RELATIVE_TRAFFIC strategy");
    Assert.assertTrue(darkClusterConfig.hasTransportClientProperties());
    D2TransportClientProperties returnedTransportClientProperties = darkClusterConfig.getTransportClientProperties();
    Assert.assertNotNull(returnedTransportClientProperties);
    Assert.assertTrue(returnedTransportClientProperties.hasRequestTimeout());
    Assert.assertEquals(Objects.requireNonNull(returnedTransportClientProperties.getRequestTimeout()).longValue(), 1000, "expected 1000 request Timeout");
}
Also used : DarkClusterConfigMap(com.linkedin.d2.DarkClusterConfigMap) DarkClusterStrategyNameArray(com.linkedin.d2.DarkClusterStrategyNameArray) DarkClusterConfig(com.linkedin.d2.DarkClusterConfig) D2TransportClientProperties(com.linkedin.d2.D2TransportClientProperties) Test(org.testng.annotations.Test)

Aggregations

DarkClusterStrategyNameArray (com.linkedin.d2.DarkClusterStrategyNameArray)10 DarkClusterConfig (com.linkedin.d2.DarkClusterConfig)8 Test (org.testng.annotations.Test)6 DarkClusterConfigMap (com.linkedin.d2.DarkClusterConfigMap)5 NoOpDarkClusterStrategy (com.linkedin.darkcluster.api.NoOpDarkClusterStrategy)4 DarkClusterStrategy (com.linkedin.darkcluster.api.DarkClusterStrategy)3 RelativeTrafficMultiplierDarkClusterStrategy (com.linkedin.darkcluster.impl.RelativeTrafficMultiplierDarkClusterStrategy)3 ArrayList (java.util.ArrayList)3 HashMap (java.util.HashMap)3 D2TransportClientProperties (com.linkedin.d2.D2TransportClientProperties)2 Map (java.util.Map)2 DarkClusterStrategyName (com.linkedin.d2.DarkClusterStrategyName)1 BaseDarkClusterDispatcher (com.linkedin.darkcluster.api.BaseDarkClusterDispatcher)1 DataList (com.linkedin.data.DataList)1 ConstantQpsRateLimiter (com.linkedin.r2.transport.http.client.ConstantQpsRateLimiter)1 List (java.util.List)1