use of com.linkedin.d2.balancer.properties.UriProperties in project rest.li by linkedin.
the class ZKFSTogglingLoadBalancerFactoryImpl method createLoadBalancer.
@Override
public TogglingLoadBalancer createLoadBalancer(ZKConnection zkConnection, ScheduledExecutorService executorService) {
_log.info("Using d2ServicePath: " + _d2ServicePath);
ZooKeeperPermanentStore<ClusterProperties> zkClusterRegistry = createPermanentStore(zkConnection, ZKFSUtil.clusterPath(_baseZKPath), new ClusterPropertiesJsonSerializer());
ZooKeeperPermanentStore<ServiceProperties> zkServiceRegistry = createPermanentStore(zkConnection, ZKFSUtil.servicePath(_baseZKPath, _d2ServicePath), new ServicePropertiesJsonSerializer());
ZooKeeperEphemeralStore<UriProperties> zkUriRegistry = createEphemeralStore(zkConnection, ZKFSUtil.uriPath(_baseZKPath), new UriPropertiesJsonSerializer(), new UriPropertiesMerger(), _useNewEphemeralStoreWatcher);
FileStore<ClusterProperties> fsClusterStore = createFileStore("clusters", new ClusterPropertiesJsonSerializer());
FileStore<ServiceProperties> fsServiceStore = createFileStore(_d2ServicePath, new ServicePropertiesJsonSerializer());
FileStore<UriProperties> fsUriStore = createFileStore("uris", new UriPropertiesJsonSerializer());
PropertyEventBus<ClusterProperties> clusterBus = new PropertyEventBusImpl<ClusterProperties>(executorService);
PropertyEventBus<ServiceProperties> serviceBus = new PropertyEventBusImpl<ServiceProperties>(executorService);
PropertyEventBus<UriProperties> uriBus = new PropertyEventBusImpl<UriProperties>(executorService);
// This ensures the filesystem store receives the events from the event bus so that
// it can keep a local backup.
clusterBus.register(fsClusterStore);
serviceBus.register(fsServiceStore);
uriBus.register(fsUriStore);
TogglingPublisher<ClusterProperties> clusterToggle = _factory.createClusterToggle(zkClusterRegistry, fsClusterStore, clusterBus);
TogglingPublisher<ServiceProperties> serviceToggle = _factory.createServiceToggle(zkServiceRegistry, fsServiceStore, serviceBus);
TogglingPublisher<UriProperties> uriToggle = _factory.createUriToggle(zkUriRegistry, fsUriStore, uriBus);
SimpleLoadBalancerState state = new SimpleLoadBalancerState(executorService, uriBus, clusterBus, serviceBus, _clientFactories, _loadBalancerStrategyFactories, _sslContext, _sslParameters, _isSSLEnabled, _clientServicesConfig);
SimpleLoadBalancer balancer = new SimpleLoadBalancer(state, _lbTimeout, _lbTimeoutUnit);
TogglingLoadBalancer togLB = _factory.createBalancer(balancer, state, clusterToggle, serviceToggle, uriToggle);
togLB.start(new Callback<None>() {
@Override
public void onError(Throwable e) {
_log.warn("Failed to run start on the TogglingLoadBalancer, may not have registered " + "SimpleLoadBalancer and State with JMX.");
}
@Override
public void onSuccess(None result) {
_log.info("Registered SimpleLoadBalancer and State with JMX.");
}
});
return togLB;
}
use of com.linkedin.d2.balancer.properties.UriProperties in project rest.li by linkedin.
the class LoadBalancerTestState method getUriProperties.
@Override
public LoadBalancerStateItem<UriProperties> getUriProperties(String clusterName) {
try {
URI uri1 = URI.create("http://test.qa1.com:1234");
URI uri2 = URI.create("http://test.qa2.com:2345");
URI uri3 = URI.create("http://test.qa3.com:6789");
Map<Integer, PartitionData> partitionData = new HashMap<Integer, PartitionData>(1);
partitionData.put(DefaultPartitionAccessor.DEFAULT_PARTITION_ID, new PartitionData(1d));
Map<URI, Map<Integer, PartitionData>> uriData = new HashMap<URI, Map<Integer, PartitionData>>(3);
uriData.put(uri1, partitionData);
uriData.put(uri2, partitionData);
uriData.put(uri3, partitionData);
return (getUriProperties) ? new LoadBalancerStateItem<UriProperties>(new UriProperties("cluster-1", uriData), 0, 0) : null;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
use of com.linkedin.d2.balancer.properties.UriProperties in project rest.li by linkedin.
the class SimpleLoadBalancerDelayTest method testLoadBalancerWithSlowStartClient.
@Test(groups = { "small", "back-end" }, enabled = false)
public void testLoadBalancerWithSlowStartClient() throws Exception {
// Generate service, cluster and uri properties for d2
URI uri1 = URI.create("http://test.qa1.com:1234");
URI uri2 = URI.create("http://test.qa2.com:2345");
URI uri3 = URI.create("http://test.qa3.com:6789");
String clusterName = "cluster-2";
Map<Integer, PartitionData> partitionData = new HashMap<>(1);
partitionData.put(DefaultPartitionAccessor.DEFAULT_PARTITION_ID, new PartitionData(1d));
Map<URI, Map<Integer, PartitionData>> uriData = new HashMap<>(3);
uriData.put(uri1, partitionData);
uriData.put(uri2, partitionData);
uriData.put(uri3, partitionData);
ClusterProperties clusterProperties = new ClusterProperties(clusterName);
List<String> prioritizedSchemes = Collections.singletonList("http");
// enable multi-probe consistent hashing
Map<String, Object> lbStrategyProperties = Collections.singletonMap(PropertyKeys.HTTP_LB_CONSISTENT_HASH_ALGORITHM, DegraderRingFactory.MULTI_PROBE_CONSISTENT_HASH);
// set initial drop rate and slow start threshold
Map<String, String> degraderProperties = new HashMap<>();
degraderProperties.put(PropertyKeys.DEGRADER_INITIAL_DROP_RATE, "0.99");
degraderProperties.put(PropertyKeys.DEGRADER_SLOW_START_THRESHOLD, "0.1");
// constant delay generator
LoadBalancerSimulator.TimedValueGenerator<String> delayGenerator = (uri, time, unit) -> 100l;
// constant QPS generator
LoadBalancerSimulator.QPSGenerator qpsGenerator = () -> 1000;
Map<String, Object> transportClientProperties = Collections.singletonMap("DelayGenerator", delayGenerator);
ServiceProperties serviceProperties = new ServiceProperties("foo", clusterName, "/foo", Arrays.asList("degrader"), lbStrategyProperties, transportClientProperties, degraderProperties, prioritizedSchemes, null);
UriProperties uriProperties = new UriProperties(clusterName, uriData);
// pass all the info to the simulator
LoadBalancerSimulator loadBalancerSimulator = new LoadBalancerSimulator(serviceProperties, clusterProperties, uriProperties, delayGenerator, qpsGenerator);
// Start the simulation, wait for 10 UPDATE_INTERVALS to make sure all uris are fully ramped.
loadBalancerSimulator.runWait(DegraderLoadBalancerStrategyConfig.DEFAULT_UPDATE_INTERVAL_MS * 20);
printStates(loadBalancerSimulator);
URI uri4 = URI.create("http://test.qa4.com:9876");
uriData.put(uri4, partitionData);
uriProperties = new UriProperties(clusterName, uriData);
loadBalancerSimulator.updateUriProperties(uriProperties);
loadBalancerSimulator.runWait(DegraderLoadBalancerStrategyConfig.DEFAULT_UPDATE_INTERVAL_MS);
printStates(loadBalancerSimulator);
// Create the delay generator for the uris
URI expectedUri4 = URI.create("http://test.qa4.com:9876/foo");
loadBalancerSimulator.getCountPercent(expectedUri4);
// the points for uri4 should be 1 and call count percentage is 0.3%.
double callCountPercent = loadBalancerSimulator.getCountPercent(expectedUri4);
assertTrue(callCountPercent <= 0.006, "expected percentage is less than 0.006, actual is " + callCountPercent);
// wait for 2 intervals due to call dropping
loadBalancerSimulator.runWait(DegraderLoadBalancerStrategyConfig.DEFAULT_UPDATE_INTERVAL_MS * 2);
printStates(loadBalancerSimulator);
// the points for uri4 should be 4 and call count percentage is 1.3%
callCountPercent = loadBalancerSimulator.getCountPercent(expectedUri4);
assertTrue(callCountPercent <= 0.02, "expected percentage is less than 0.02, actual is " + callCountPercent);
// wait for 2 intervals due to call dropping
loadBalancerSimulator.runWait(DegraderLoadBalancerStrategyConfig.DEFAULT_UPDATE_INTERVAL_MS * 2);
printStates(loadBalancerSimulator);
// the points for uri4 should be 16 and call count percentage is 5%
callCountPercent = loadBalancerSimulator.getCountPercent(expectedUri4);
assertTrue(callCountPercent <= 0.07, "expected percentage is less than 0.07, actual is " + callCountPercent);
assertTrue(callCountPercent >= 0.03, "expected percentage is larger than 0.03, actual is " + callCountPercent);
// wait for 2 intervals due to call dropping
loadBalancerSimulator.runWait(DegraderLoadBalancerStrategyConfig.DEFAULT_UPDATE_INTERVAL_MS * 2);
printStates(loadBalancerSimulator);
// the points for uri4 should be 56 and call count percentage is 16%
callCountPercent = loadBalancerSimulator.getCountPercent(expectedUri4);
assertTrue(callCountPercent <= 0.18, "expected percentage is less than 0.18, actual is " + callCountPercent);
assertTrue(callCountPercent >= 0.12, "expected percentage is larger than 0.12, actual is " + callCountPercent);
// wait for 2 intervals due to call dropping
loadBalancerSimulator.runWait(DegraderLoadBalancerStrategyConfig.DEFAULT_UPDATE_INTERVAL_MS * 2);
printStates(loadBalancerSimulator);
// the points for uri4 should be 96 and call count percentage is 24%
callCountPercent = loadBalancerSimulator.getCountPercent(expectedUri4);
assertTrue(callCountPercent <= 0.28, "expected percentage is less than 0.26, actual is " + callCountPercent);
assertTrue(callCountPercent >= 0.20, "expected percentage is larger than 0.22, actual is " + callCountPercent);
}
use of com.linkedin.d2.balancer.properties.UriProperties in project rest.li by linkedin.
the class SimpleLoadBalancerDelayTest method testLoadBalancerWithDelay.
@Test(groups = { "small", "back-end" }, enabled = false)
public void testLoadBalancerWithDelay() throws Exception {
// Generate service, cluster and uri properties for d2
URI uri1 = URI.create("http://test.qa1.com:1234");
URI uri2 = URI.create("http://test.qa2.com:2345");
URI uri3 = URI.create("http://test.qa3.com:6789");
Map<Integer, PartitionData> partitionData = new HashMap<Integer, PartitionData>(1);
partitionData.put(DefaultPartitionAccessor.DEFAULT_PARTITION_ID, new PartitionData(1d));
Map<URI, Map<Integer, PartitionData>> uriData = new HashMap<URI, Map<Integer, PartitionData>>(3);
uriData.put(uri1, partitionData);
uriData.put(uri2, partitionData);
uriData.put(uri3, partitionData);
ClusterProperties clusterProperties = new ClusterProperties("cluster-1");
List<String> prioritizedSchemes = Collections.singletonList("http");
ServiceProperties serviceProperties = new ServiceProperties("foo", "cluster-1", "/foo", Arrays.asList("degrader"), Collections.emptyMap(), null, null, prioritizedSchemes, null);
UriProperties uriProperties = new UriProperties("cluster-1", uriData);
// Create the delay generator for the uris
URI expectedUri1 = URI.create("http://test.qa1.com:1234/foo");
URI expectedUri2 = URI.create("http://test.qa2.com:2345/foo");
URI expectedUri3 = URI.create("http://test.qa3.com:6789/foo");
// Construct the delay patterns: for each URI there is a list of delays for each interval
Map<String, List<Long>> delayMaps = new HashMap<>();
delayMaps.put("http://test.qa1.com:1234/foo", Arrays.asList(50l, 60l, 75l, 55l, 60l, 80l, 50l));
delayMaps.put("http://test.qa1.com:2345/foo", Arrays.asList(60l, 60l, 50l, 60l, 50l, 80l, 50l));
delayMaps.put("http://test.qa1.com:6789/foo", Arrays.asList(80l, 3000l, 3000l, 3000l, 5000l, 80l, 50l));
LoadBalancerSimulator.TimedValueGenerator<String> delayGenerator = new DelayValueGenerator(delayMaps, DegraderLoadBalancerStrategyConfig.DEFAULT_UPDATE_INTERVAL_MS);
// Construct the QPS generator
LoadBalancerSimulator.QPSGenerator qpsGenerator = new ConstantQPSGenerator(1000);
// pass all the info to the simulator
LoadBalancerSimulator loadBalancerSimulator = new LoadBalancerSimulator(serviceProperties, clusterProperties, uriProperties, delayGenerator, qpsGenerator);
// Start the simulation
loadBalancerSimulator.runWait(DegraderLoadBalancerStrategyConfig.DEFAULT_UPDATE_INTERVAL_MS);
printStates(loadBalancerSimulator);
// the points for uri3 should be 100
assertEquals(loadBalancerSimulator.getPoint("foo", DefaultPartitionAccessor.DEFAULT_PARTITION_ID, uri3), 100);
// the uri3 should be used around 33% of all queries. Due to the hashring variance we need
// to check the range.
// uri3 will be degrading further after the previous interval
// assertTrue(loadBalancerSimulator.getCountPercent(expectedUri3) <= 0.375);
// assertTrue(loadBalancerSimulator.getCountPercent(expectedUri3) >= 0.295);
// wait for 2 intervals due to call dropping involved
loadBalancerSimulator.runWait(DegraderLoadBalancerStrategyConfig.DEFAULT_UPDATE_INTERVAL_MS * 2);
printStates(loadBalancerSimulator);
// the points for uri3 should be 80
// Also if the loadbalancing strategy changed, the numbers could be lower
assertEquals(loadBalancerSimulator.getPoint("foo", DefaultPartitionAccessor.DEFAULT_PARTITION_ID, uri3), 80);
// the uri3 should be used around 28%, will be degrading further next
// assertTrue(loadBalancerSimulator.getCountPercent(expectedUri3) <= 0.32);
// assertTrue(loadBalancerSimulator.getCountPercent(expectedUri3) >= 0.24);
// continue the simulation
loadBalancerSimulator.runWait(DegraderLoadBalancerStrategyConfig.DEFAULT_UPDATE_INTERVAL_MS * 2);
printStates(loadBalancerSimulator);
// the points for uri3 should be around 40
assertEquals(loadBalancerSimulator.getPoint("foo", DefaultPartitionAccessor.DEFAULT_PARTITION_ID, uri3), 39);
// the uri3 should be used around 16%, will be recovering next
// assertTrue(loadBalancerSimulator.getCountPercent(expectedUri3) <= 0.20);
// assertTrue(loadBalancerSimulator.getCountPercent(expectedUri3) >= 0.12);
loadBalancerSimulator.runWait(DegraderLoadBalancerStrategyConfig.DEFAULT_UPDATE_INTERVAL_MS * 3);
printStates(loadBalancerSimulator);
// the points for uri3 should be around 60, recovering
assertEquals(loadBalancerSimulator.getPoint("foo", DefaultPartitionAccessor.DEFAULT_PARTITION_ID, uri3), 59);
// Done. Shutdown the simulation
loadBalancerSimulator.shutdown();
}
use of com.linkedin.d2.balancer.properties.UriProperties in project rest.li by linkedin.
the class SimpleLoadBalancerStateTest method testSSLDisabledWithHttpsInstances.
@Test(groups = { "small", "back-end" })
public void testSSLDisabledWithHttpsInstances() throws URISyntaxException {
reset();
URI uri = URI.create("http://cluster-1/test");
URI httpsUri = URI.create("https://cluster-1/test");
List<String> schemes = new ArrayList<String>();
Map<Integer, PartitionData> partitionData = new HashMap<Integer, PartitionData>(1);
partitionData.put(DefaultPartitionAccessor.DEFAULT_PARTITION_ID, new PartitionData(1d));
Map<URI, Map<Integer, PartitionData>> uriData = new HashMap<URI, Map<Integer, PartitionData>>();
uriData.put(uri, partitionData);
uriData.put(httpsUri, partitionData);
schemes.add("https");
schemes.add("http");
assertNull(_state.getClient("service-1", uri));
// set up state
_state.listenToCluster("cluster-1", new NullStateListenerCallback());
assertNull(_state.getClient("service-1", uri));
_state.listenToService("service-1", new NullStateListenerCallback());
assertNull(_state.getClient("service-1", uri));
Map<String, Object> transportClientProperties = new HashMap<String, Object>();
transportClientProperties.put(HttpClientFactory.HTTP_SSL_CONTEXT, _sslContext);
transportClientProperties.put(HttpClientFactory.HTTP_SSL_PARAMS, _sslParameters);
transportClientProperties = Collections.unmodifiableMap(transportClientProperties);
ServiceProperties serviceProperties = new ServiceProperties("service-1", "cluster-1", "/test", Arrays.asList("random"), Collections.<String, Object>emptyMap(), transportClientProperties, null, schemes, null);
_serviceRegistry.put("service-1", serviceProperties);
assertNull(_state.getClient("service-1", uri));
_uriRegistry.put("cluster-1", new UriProperties("cluster-1", uriData));
List<LoadBalancerState.SchemeStrategyPair> schemeStrategyPairs = _state.getStrategiesForService("service-1", schemes);
for (LoadBalancerState.SchemeStrategyPair pair : schemeStrategyPairs) {
assertFalse("https".equalsIgnoreCase(pair.getScheme()), "https shouldn't be in any schemeStrategyPair");
}
TrackerClient client = _state.getClient("service-1", uri);
assertNotNull(client);
assertEquals(client.getUri(), uri);
// Unfortunately, I don't know a good way to intercept the logs
client = _state.getClient("service-1", httpsUri);
assertNull(client, "shouldn't pick an https uri");
_state.refreshTransportClientsPerService(serviceProperties);
}
Aggregations