use of com.linkedin.d2.ConsistentHashAlgorithm in project rest.li by linkedin.
the class LoadBalancerStrategyPropertiesConverter method toConfig.
@SuppressWarnings({ "unchecked" })
public static D2LoadBalancerStrategyProperties toConfig(Map<String, Object> properties) {
D2LoadBalancerStrategyProperties config = new D2LoadBalancerStrategyProperties();
if (properties.containsKey(PropertyKeys.HTTP_LB_GLOBAL_STEP_DOWN)) {
config.setGlobalStepDown(coerce(properties.get(PropertyKeys.HTTP_LB_GLOBAL_STEP_DOWN), Double.class));
}
if (properties.containsKey(PropertyKeys.HTTP_LB_GLOBAL_STEP_UP)) {
config.setGlobalStepUp(coerce(properties.get(PropertyKeys.HTTP_LB_GLOBAL_STEP_UP), Double.class));
}
if (properties.containsKey(PropertyKeys.HTTP_LB_INITIAL_RECOVERY_LEVEL)) {
config.setInitialRecoveryLevel(coerce(properties.get(PropertyKeys.HTTP_LB_INITIAL_RECOVERY_LEVEL), Double.class));
}
if (properties.containsKey(PropertyKeys.HTTP_LB_RING_RAMP_FACTOR)) {
config.setRingRampFactor(coerce(properties.get(PropertyKeys.HTTP_LB_RING_RAMP_FACTOR), Double.class));
}
if (properties.containsKey(PropertyKeys.HTTP_LB_HIGH_WATER_MARK)) {
config.setHighWaterMark(coerce(properties.get(PropertyKeys.HTTP_LB_HIGH_WATER_MARK), Double.class));
}
if (properties.containsKey(PropertyKeys.HTTP_LB_LOW_WATER_MARK)) {
config.setLowWaterMark(coerce(properties.get(PropertyKeys.HTTP_LB_LOW_WATER_MARK), Double.class));
}
if (properties.containsKey(PropertyKeys.HTTP_LB_STRATEGY_PROPERTIES_POINTS_PER_WEIGHT)) {
config.setPointsPerWeight(coerce(properties.get(PropertyKeys.HTTP_LB_STRATEGY_PROPERTIES_POINTS_PER_WEIGHT), Integer.class));
}
if (properties.containsKey(PropertyKeys.HTTP_LB_STRATEGY_PROPERTIES_UPDATE_INTERVAL_MS)) {
config.setUpdateIntervalMs(coerce(properties.get(PropertyKeys.HTTP_LB_STRATEGY_PROPERTIES_UPDATE_INTERVAL_MS), Long.class));
}
if (properties.containsKey(PropertyKeys.HTTP_LB_CLUSTER_MIN_CALL_COUNT_HIGH_WATER_MARK)) {
config.setMinCallCountHighWaterMark(coerce(properties.get(PropertyKeys.HTTP_LB_CLUSTER_MIN_CALL_COUNT_HIGH_WATER_MARK), Long.class));
}
if (properties.containsKey(PropertyKeys.HTTP_LB_CLUSTER_MIN_CALL_COUNT_LOW_WATER_MARK)) {
config.setMinCallCountLowWaterMark(coerce(properties.get(PropertyKeys.HTTP_LB_CLUSTER_MIN_CALL_COUNT_LOW_WATER_MARK), Long.class));
}
if (properties.containsKey(PropertyKeys.HTTP_LB_HASHRING_POINT_CLEANUP_RATE)) {
config.setHashRingPointCleanupRate(coerce(properties.get(PropertyKeys.HTTP_LB_HASHRING_POINT_CLEANUP_RATE), Double.class));
}
if (properties.containsKey(PropertyKeys.HTTP_LB_HASH_METHOD)) {
String hashMethodString = coerce(properties.get(PropertyKeys.HTTP_LB_HASH_METHOD), String.class);
if (DegraderLoadBalancerStrategyV3.HASH_METHOD_NONE.equalsIgnoreCase(hashMethodString)) {
config.setHashMethod(hashMethodEnum.RANDOM);
} else if (DegraderLoadBalancerStrategyV3.HASH_METHOD_URI_REGEX.equalsIgnoreCase(hashMethodString)) {
config.setHashMethod(hashMethodEnum.URI_REGEX);
}
}
if (properties.containsKey(PropertyKeys.HTTP_LB_HASH_CONFIG)) {
hashConfigType hashConfig = new hashConfigType();
Map<String, Object> hashConfigProperties = (Map<String, Object>) properties.get(PropertyKeys.HTTP_LB_HASH_CONFIG);
if (hashConfigProperties.containsKey(URIRegexHash.KEY_REGEXES)) {
List<String> uriRegexes = (List<String>) hashConfigProperties.get(URIRegexHash.KEY_REGEXES);
hashConfig.setUriRegexes(new StringArray(uriRegexes));
}
if (hashConfigProperties.containsKey(URIRegexHash.KEY_WARN_ON_NO_MATCH)) {
String warnOnNoMatchString = (String) hashConfigProperties.get(URIRegexHash.KEY_WARN_ON_NO_MATCH);
hashConfig.setWarnOnNoMatch(Boolean.parseBoolean(warnOnNoMatchString));
}
if (hashConfigProperties.containsKey(URIRegexHash.KEY_FAIL_ON_NO_MATCH)) {
String failOnNoMatchString = (String) hashConfigProperties.get(URIRegexHash.KEY_FAIL_ON_NO_MATCH);
hashConfig.setFailOnNoMatch(Boolean.parseBoolean(failOnNoMatchString));
}
config.setHashConfig(hashConfig);
}
if (properties.containsKey(PropertyKeys.HTTP_LB_STRATEGY_PROPERTIES_UPDATE_ONLY_AT_INTERVAL)) {
config.setUpdateOnlyAtInterval(coerce(properties.get(PropertyKeys.HTTP_LB_STRATEGY_PROPERTIES_UPDATE_ONLY_AT_INTERVAL), Boolean.class));
}
if (properties.containsKey(PropertyKeys.HTTP_LB_CONSISTENT_HASH_ALGORITHM)) {
String consistentHashAlgorithm = coerce(properties.get(PropertyKeys.HTTP_LB_CONSISTENT_HASH_ALGORITHM), String.class);
if (DelegatingRingFactory.POINT_BASED_CONSISTENT_HASH.equalsIgnoreCase(consistentHashAlgorithm)) {
config.setConsistentHashAlgorithm(ConsistentHashAlgorithmEnum.POINT_BASED);
} else if (DelegatingRingFactory.MULTI_PROBE_CONSISTENT_HASH.equalsIgnoreCase(consistentHashAlgorithm)) {
config.setConsistentHashAlgorithm(ConsistentHashAlgorithmEnum.MULTI_PROBE);
} else if (DelegatingRingFactory.DISTRIBUTION_NON_HASH.equalsIgnoreCase(consistentHashAlgorithm)) {
config.setConsistentHashAlgorithm(ConsistentHashAlgorithmEnum.DISTRIBUTION_BASED);
}
}
if (properties.containsKey(PropertyKeys.HTTP_LB_CONSISTENT_HASH_NUM_PROBES)) {
config.setNumberOfProbes(coerce(properties.get(PropertyKeys.HTTP_LB_CONSISTENT_HASH_NUM_PROBES), Integer.class));
}
if (properties.containsKey(PropertyKeys.HTTP_LB_CONSISTENT_HASH_POINTS_PER_HOST)) {
config.setNumberOfPointsPerHost(coerce(properties.get(PropertyKeys.HTTP_LB_CONSISTENT_HASH_POINTS_PER_HOST), Integer.class));
}
if (properties.containsKey(PropertyKeys.HTTP_LB_CONSISTENT_HASH_BOUNDED_LOAD_BALANCING_FACTOR)) {
config.setBoundedLoadBalancingFactor(coerce(properties.get(PropertyKeys.HTTP_LB_CONSISTENT_HASH_BOUNDED_LOAD_BALANCING_FACTOR), Double.class));
}
if (properties.containsKey(PropertyKeys.HTTP_LB_QUARANTINE_MAX_PERCENT) || properties.containsKey(PropertyKeys.HTTP_LB_QUARANTINE_METHOD)) {
quarantineInfo quarantineInfo = new quarantineInfo();
if (properties.containsKey(PropertyKeys.HTTP_LB_QUARANTINE_MAX_PERCENT)) {
quarantineInfo.setQuarantineMaxPercent(coerce(properties.get(PropertyKeys.HTTP_LB_QUARANTINE_MAX_PERCENT), Double.class));
}
if (properties.containsKey(PropertyKeys.HTTP_LB_QUARANTINE_METHOD)) {
quarantineInfo.setQuarantineMethod(coerce(properties.get(PropertyKeys.HTTP_LB_QUARANTINE_METHOD), String.class));
}
config.setQuarantineCfg(quarantineInfo);
}
if (properties.containsKey(PropertyKeys.HTTP_LB_ERROR_STATUS_REGEX)) {
config.setErrorStatusRegex(coerce(properties.get(PropertyKeys.HTTP_LB_ERROR_STATUS_REGEX), String.class));
}
if (properties.containsKey(PropertyKeys.HTTP_LB_LOW_EVENT_EMITTING_INTERVAL)) {
config.setLowEmittingInterval(coerce(properties.get(PropertyKeys.HTTP_LB_LOW_EVENT_EMITTING_INTERVAL), Integer.class));
}
if (properties.containsKey(PropertyKeys.HTTP_LB_HIGH_EVENT_EMITTING_INTERVAL)) {
config.setHighEmittingInterval(coerce(properties.get(PropertyKeys.HTTP_LB_HIGH_EVENT_EMITTING_INTERVAL), Integer.class));
}
return config;
}
use of com.linkedin.d2.ConsistentHashAlgorithm in project rest.li by linkedin.
the class RelativeStrategyPropertiesConverter method toRingProperties.
@SuppressWarnings({ "unchecked" })
private static D2RingProperties toRingProperties(Map<String, Object> ringPropertyMap) {
D2RingProperties ringProperties = new D2RingProperties();
if (ringPropertyMap.containsKey(PropertyKeys.RING_POINTS_PER_WEIGHT)) {
ringProperties.setPointsPerWeight(coerce(ringPropertyMap.get(PropertyKeys.RING_POINTS_PER_WEIGHT), Integer.class));
}
if (ringPropertyMap.containsKey(PropertyKeys.RING_HASH_METHOD)) {
String hashMethod = (String) ringPropertyMap.get(PropertyKeys.RING_HASH_METHOD);
if (HashMethod.URI_REGEX.name().equalsIgnoreCase(hashMethod) || RelativeLoadBalancerStrategy.HASH_METHOD_URI_REGEX.equalsIgnoreCase(hashMethod)) {
ringProperties.setHashMethod(HashMethod.URI_REGEX);
} else if (HashMethod.RANDOM.name().equalsIgnoreCase(hashMethod)) {
ringProperties.setHashMethod(HashMethod.RANDOM);
}
}
if (ringPropertyMap.containsKey(PropertyKeys.RING_HASH_CONFIG)) {
HashConfig hashConfig = toHashConfig((Map<String, Object>) ringPropertyMap.get(PropertyKeys.RING_HASH_CONFIG));
ringProperties.setHashConfig(hashConfig);
}
if (ringPropertyMap.containsKey(PropertyKeys.RING_HASH_RING_POINT_CLEANUP_RATE)) {
ringProperties.setHashRingPointCleanupRate(coerce(ringPropertyMap.get(PropertyKeys.RING_HASH_RING_POINT_CLEANUP_RATE), Double.class));
}
if (ringPropertyMap.containsKey(PropertyKeys.RING_CONSISTENT_HASH_ALGORITHM)) {
String consistentHashAlgorithm = (String) ringPropertyMap.get(PropertyKeys.RING_CONSISTENT_HASH_ALGORITHM);
if (DelegatingRingFactory.POINT_BASED_CONSISTENT_HASH.equalsIgnoreCase(consistentHashAlgorithm)) {
ringProperties.setConsistentHashAlgorithm(ConsistentHashAlgorithm.POINT_BASED);
} else if (DelegatingRingFactory.MULTI_PROBE_CONSISTENT_HASH.equalsIgnoreCase(consistentHashAlgorithm)) {
ringProperties.setConsistentHashAlgorithm(ConsistentHashAlgorithm.MULTI_PROBE);
} else if (DelegatingRingFactory.DISTRIBUTION_NON_HASH.equalsIgnoreCase(consistentHashAlgorithm)) {
ringProperties.setConsistentHashAlgorithm(ConsistentHashAlgorithm.DISTRIBUTION_BASED);
}
}
if (ringPropertyMap.containsKey(PropertyKeys.RING_NUMBER_OF_PROBES)) {
ringProperties.setNumberOfProbes(coerce(ringPropertyMap.get(PropertyKeys.RING_NUMBER_OF_PROBES), Integer.class));
}
if (ringPropertyMap.containsKey(PropertyKeys.RING_NUMBER_OF_POINTS_PER_HOST)) {
ringProperties.setNumberOfPointsPerHost(coerce(ringPropertyMap.get(PropertyKeys.RING_NUMBER_OF_POINTS_PER_HOST), Integer.class));
}
if (ringPropertyMap.containsKey(PropertyKeys.RING_BOUNDED_LOAD_BALANCING_FACTOR)) {
ringProperties.setBoundedLoadBalancingFactor(coerce(ringPropertyMap.get(PropertyKeys.RING_BOUNDED_LOAD_BALANCING_FACTOR), Double.class));
}
return ringProperties;
}
use of com.linkedin.d2.ConsistentHashAlgorithm in project rest.li by linkedin.
the class DegraderLoadBalancerTest method testWeightedBalancingRing.
@Test(groups = { "small", "back-end" }, dataProvider = "consistentHashAlgorithms")
public void testWeightedBalancingRing(String consistentHashAlgorithm) throws URISyntaxException {
DegraderLoadBalancerStrategyV3 strategy = getStrategy(consistentHashAlgorithm);
List<DegraderTrackerClient> clients = new ArrayList<>();
URI uri1 = URI.create("http://test.linkedin.com:3242/fdsaf");
URI uri2 = URI.create("http://test.linkedin.com:3243/fdsaf");
TestClock clock1 = new TestClock();
TestClock clock2 = new TestClock();
DegraderTrackerClient client1 = new DegraderTrackerClientImpl(uri1, getDefaultPartitionData(1d), new TestLoadBalancerClient(uri1), clock1, null);
DegraderTrackerClient client2 = new DegraderTrackerClientImpl(uri2, getDefaultPartitionData(0.8d), new TestLoadBalancerClient(uri2), clock2, null);
clients.add(client1);
clients.add(client2);
// trigger a state update
assertNotNull(getTrackerClient(strategy, null, new RequestContext(), 1, clients));
// now do a basic verification to verify getTrackerClient is properly weighting things
double calls = 10000d;
int client1Count = 0;
int client2Count = 0;
double tolerance = 0.05d;
for (int i = 0; i < calls; ++i) {
TrackerClient client = getTrackerClient(strategy, null, new RequestContext(), 1, clients);
assertNotNull(client);
if (client.getUri().equals(uri1)) {
++client1Count;
} else {
++client2Count;
}
}
assertTrue(Math.abs((client1Count / calls) - (100 / 180d)) < tolerance);
assertTrue(Math.abs((client2Count / calls) - (80 / 180d)) < tolerance);
}
use of com.linkedin.d2.ConsistentHashAlgorithm 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);
Map<URI, TrackerClient> clientsForPartition0 = new HashMap<>();
Map<URI, TrackerClient> clientsForPartition1 = new HashMap<>();
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") DegraderTrackerClient client1 = new DegraderTrackerClientImpl(uri1, new HashMap<Integer, PartitionData>() {
{
put(0, new PartitionData(1d));
}
}, new TestLoadBalancerClient(uri1), clock1, null);
@SuppressWarnings("serial") DegraderTrackerClient client2 = new DegraderTrackerClientImpl(uri2, new HashMap<Integer, PartitionData>() {
{
put(0, new PartitionData(0.5d));
put(1, new PartitionData(0.5d));
}
}, new TestLoadBalancerClient(uri2), clock2, null);
@SuppressWarnings("serial") DegraderTrackerClient client3 = new DegraderTrackerClientImpl(uri3, new HashMap<Integer, PartitionData>() {
{
put(1, new PartitionData(1d));
}
}, new TestLoadBalancerClient(uri3), clock3, null);
final int partitionId0 = 0;
clientsForPartition0.put(client1.getUri(), client1);
clientsForPartition0.put(client2.getUri(), client2);
final int partitionId1 = 1;
clientsForPartition1.put(client2.getUri(), client2);
clientsForPartition1.put(client3.getUri(), 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.ConsistentHashAlgorithm in project rest.li by linkedin.
the class DegraderLoadBalancerTest method testWeightedAndLatencyDegradationBalancingRing.
@Test(groups = { "small", "back-end" }, dataProvider = "consistentHashAlgorithms")
public void testWeightedAndLatencyDegradationBalancingRing(String consistentHashAlgorithm) throws URISyntaxException {
DegraderLoadBalancerStrategyV3 strategy = getStrategy(consistentHashAlgorithm);
List<DegraderTrackerClient> clients = new ArrayList<>();
URI uri1 = URI.create("http://test.linkedin.com:3242/fdsaf");
URI uri2 = URI.create("http://test.linkedin.com:3243/fdsaf");
TestClock clock1 = new TestClock();
TestClock clock2 = new TestClock();
DegraderTrackerClient client1 = new DegraderTrackerClientImpl(uri1, getDefaultPartitionData(1d), new TestLoadBalancerClient(uri1), clock1, null);
DegraderTrackerClient client2 = new DegraderTrackerClientImpl(uri2, getDefaultPartitionData(0.8d), new TestLoadBalancerClient(uri2), clock2, null);
clients.add(client1);
clients.add(client2);
DegraderControl dcClient2Default = client2.getDegraderControl(DEFAULT_PARTITION_ID);
dcClient2Default.setOverrideMinCallCount(1);
dcClient2Default.setMinCallCount(1);
dcClient2Default.setMaxDropRate(1d);
dcClient2Default.setUpStep(0.4d);
dcClient2Default.setHighErrorRate(0);
CallCompletion cc = client2.getCallTracker().startCall();
clock2.addMs(1);
cc.endCallWithError();
clock1.addMs(15000);
clock2.addMs(5000);
// trigger a state update
assertNotNull(getTrackerClient(strategy, null, new RequestContext(), 1, clients));
// now do a basic verification to verify getTrackerClient is properly weighting things
double calls = 10000d;
int client1Count = 0;
int client2Count = 0;
double tolerance = 0.05d;
for (int i = 0; i < calls; ++i) {
TrackerClient client = getTrackerClient(strategy, null, new RequestContext(), 1, clients);
assertNotNull(client);
if (client.getUri().equals(uri1)) {
++client1Count;
} else {
++client2Count;
}
}
assertTrue(Math.abs((client1Count / calls) - (100 / 148d)) < tolerance);
assertTrue(Math.abs((client2Count / calls) - (48 / 148d)) < tolerance);
}
Aggregations