use of com.linkedin.d2.balancer.properties.ClusterProperties in project rest.li by linkedin.
the class SimpleLoadBalancerStateTest method testRegisterMultipleClusterListener.
@Test
public void testRegisterMultipleClusterListener() {
reset();
MockClusterListener clusterListener1 = new MockClusterListener();
_state.registerClusterListener(clusterListener1);
MockClusterListener clusterListener2 = new MockClusterListener();
_state.registerClusterListener(clusterListener2);
_state.listenToCluster(CLUSTER1_CLUSTER_NAME, new NullStateListenerCallback());
_state.listenToCluster(CLUSTER2_CLUSTER_NAME, new NullStateListenerCallback());
_clusterRegistry.put(CLUSTER1_CLUSTER_NAME, new ClusterProperties(CLUSTER1_CLUSTER_NAME));
_clusterRegistry.put(CLUSTER2_CLUSTER_NAME, new ClusterProperties(CLUSTER2_CLUSTER_NAME));
_clusterRegistry.put(CLUSTER2_CLUSTER_NAME, new ClusterProperties(CLUSTER2_CLUSTER_NAME));
assertEquals(clusterListener1.getClusterAddedCount(CLUSTER1_CLUSTER_NAME), 1, "expected 1 call for cluster1");
assertEquals(clusterListener2.getClusterAddedCount(CLUSTER2_CLUSTER_NAME), 2, "expected 2 call for cluster2");
assertEquals(clusterListener1.getClusterAddedCount(CLUSTER2_CLUSTER_NAME), 2, "expected 1 call for cluster2");
assertEquals(clusterListener2.getClusterAddedCount(CLUSTER1_CLUSTER_NAME), 1, "expected 1 call for cluster1");
}
use of com.linkedin.d2.balancer.properties.ClusterProperties in project rest.li by linkedin.
the class SimpleLoadBalancerStateTest method testRefreshWithConcurrentGetTC.
// This test is to verify a fix for a specific bug, where the d2 client receives a zookeeper
// update and concurrent getTrackerClient requests. In that case, all but the first concurrent
// requests got a null tracker client because the degraderLoadBalancerState was not fully initialized
// (hashring was empty), and this continued until the first request had atomically swamped a
// fully initialized state for other requests to use. This test failed on pre-fix code, it now
// succeeds.
@Test(groups = { "small", "back-end" })
public void testRefreshWithConcurrentGetTC() throws URISyntaxException, InterruptedException {
reset();
LinkedList<String> strategyList = new LinkedList<>();
URI uri = URI.create("http://cluster-1/test");
final List<String> schemes = new ArrayList<>();
schemes.add("http");
strategyList.add("degraderV3");
// set up state
_state.listenToService("service-1", new NullStateListenerCallback());
_state.listenToCluster("cluster-1", new NullStateListenerCallback());
assertNull(_state.getStrategy("service-1", "http"));
// Use the _clusterRegistry.put to populate the _state.clusterProperties, used by
// _state.refreshServiceStrategies
_clusterRegistry.put("cluster-1", new ClusterProperties("cluster-1"));
_serviceRegistry.put("service-1", new ServiceProperties("service-1", "cluster-1", "/test", strategyList, Collections.<String, Object>emptyMap(), Collections.<String, Object>emptyMap(), Collections.<String, String>emptyMap(), schemes, Collections.<URI>emptySet()));
LoadBalancerStrategy strategy = _state.getStrategy("service-1", "http");
assertNotNull(strategy, "got null strategy in setup");
// test serial to make sure things are working before concurrent test
TransportClient resultTC = _state.getClient("service-1", "http");
assertNotNull(resultTC, "got null tracker client in non-concurrent env");
ExecutorService myExecutor = Executors.newCachedThreadPool();
ArrayList<TcCallable> cArray = new ArrayList<>();
List<TrackerClient> clients = new ArrayList<>();
Map<Integer, PartitionData> partitionDataMap = new HashMap<>(2);
partitionDataMap.put(DefaultPartitionAccessor.DEFAULT_PARTITION_ID, new PartitionData(1d));
clients.add(new DegraderTrackerClientImpl(uri, partitionDataMap, new DegraderLoadBalancerTest.TestLoadBalancerClient(uri), SystemClock.instance(), null));
for (int i = 0; i < 20; i++) {
cArray.add(i, new TcCallable(clients, _state));
}
Runnable refreshTask = new Runnable() {
@Override
public void run() {
while (true) {
List<String> myStrategyList = new LinkedList<>();
myStrategyList.add("degraderV3");
_state.refreshServiceStrategies(new ServiceProperties("service-1", "cluster-1", "/test", myStrategyList, Collections.<String, Object>emptyMap(), Collections.<String, Object>emptyMap(), Collections.<String, String>emptyMap(), schemes, Collections.<URI>emptySet()));
if (Thread.interrupted()) {
return;
}
}
}
};
myExecutor.execute(refreshTask);
Integer badResults = 0;
ArrayList<Future<Integer>> myList = new ArrayList<>();
for (int i = 0; i < cArray.size(); i++) {
@SuppressWarnings("unchecked") Callable<Integer> c = (Callable) cArray.get(i);
myList.add(i, myExecutor.submit(c));
}
try {
for (int i = 0; i < cArray.size(); i++) {
badResults += myList.get(i).get();
}
} catch (ExecutionException e) {
Assert.assertFalse(true, "got ExecutionException");
} finally {
try {
// call shutdownNow() to send an interrupt to the refreshTask
myExecutor.shutdownNow();
boolean status = myExecutor.awaitTermination(5, TimeUnit.SECONDS);
if (status == false) {
Assert.assertFalse(true, "failed to shutdown threads correctly");
}
} catch (InterruptedException ie) {
// this thread was interrupted
myExecutor.shutdownNow();
}
}
Assert.assertTrue(badResults == 0, "getTrackerClients returned null");
}
use of com.linkedin.d2.balancer.properties.ClusterProperties in project rest.li by linkedin.
the class SimpleLoadBalancerStateTest method testUnregister.
@Test(groups = { "small", "back-end" })
public void testUnregister() {
reset();
TestListener listener = new TestListener();
List<String> schemes = new ArrayList<>();
schemes.add("http");
_state.register(listener);
assertNull(listener.scheme);
assertNull(listener.strategy);
assertNull(listener.serviceName);
// trigger a strategy add
// first add a cluster
_state.listenToCluster("cluster-1", new NullStateListenerCallback());
_clusterRegistry.put("cluster-1", new ClusterProperties("cluster-1"));
// then add a service
_state.listenToService("service-1", new NullStateListenerCallback());
_serviceRegistry.put("service-1", new ServiceProperties("service-1", "cluster-1", "/test", Arrays.asList("random"), Collections.<String, Object>emptyMap(), null, null, schemes, null));
// this should trigger a refresh
assertEquals(listener.scheme, "http");
assertTrue(listener.strategy instanceof RandomLoadBalancerStrategy);
assertEquals(listener.serviceName, "service-1");
_state.unregister(listener);
// then update the cluster
_clusterRegistry.put("cluster-1", new ClusterProperties("cluster-1"));
// there should be no update here, since we unregistered
assertEquals(listener.scheme, "http");
assertTrue(listener.strategy instanceof RandomLoadBalancerStrategy);
assertEquals(listener.serviceName, "service-1");
}
use of com.linkedin.d2.balancer.properties.ClusterProperties in project rest.li by linkedin.
the class MockLBFactory method createLoadBalancer.
static SimpleLoadBalancer createLoadBalancer() {
// define the load balancing strategies that we support (round robin, etc)
Map<String, LoadBalancerStrategyFactory<? extends LoadBalancerStrategy>> loadBalancerStrategyFactories = new HashMap<>();
loadBalancerStrategyFactories.put("degrader", new DegraderLoadBalancerStrategyFactoryV3());
Map<String, TransportClientFactory> clientFactories = new HashMap<>();
clientFactories.put("http", new HttpClientFactory.Builder().build());
SynchronousExecutorService executorService = new SynchronousExecutorService();
MockStore<ServiceProperties> serviceRegistry = new MockStore<>();
MockStore<ClusterProperties> clusterRegistry = new MockStore<>();
MockStore<UriProperties> uriRegistry = new MockStore<>();
SimpleLoadBalancerState state = new SimpleLoadBalancerState(executorService, uriRegistry, clusterRegistry, serviceRegistry, clientFactories, loadBalancerStrategyFactories);
state.listenToService("greetings", new LoadBalancerState.NullStateListenerCallback());
state.listenToService("groups", new LoadBalancerState.NullStateListenerCallback());
state.listenToCluster("testcluster", new LoadBalancerState.NullStateListenerCallback());
state.listenToCluster("badcluster", new LoadBalancerState.NullStateListenerCallback());
List<String> schemes = new ArrayList<>();
schemes.add("http");
Map<String, Object> metadataProperties = new HashMap<>();
metadataProperties.put(RestConstants.RESTLI_PROTOCOL_VERSION_PROPERTY, AllProtocolVersions.BASELINE_PROTOCOL_VERSION.toString());
serviceRegistry.put("greetings", new ServiceProperties("greetings", "testcluster", "/greetings", Arrays.asList("degrader"), Collections.<String, Object>emptyMap(), null, null, schemes, null, metadataProperties));
serviceRegistry.put("groups", new ServiceProperties("groups", "badcluster", "/groups", Arrays.asList("degrader"), Collections.<String, Object>emptyMap(), null, null, schemes, null, metadataProperties));
clusterRegistry.put("testcluster", new ClusterProperties("testcluster"));
clusterRegistry.put("badcluster", new ClusterProperties("badcluster"));
uriRegistry.put("testcluster", new UriProperties("testcluster", createUriData("http://localhost:1338")));
uriRegistry.put("badcluster", new UriProperties("badcluster", createUriData("http://localhost:1337")));
// create the load balancer
return new SimpleLoadBalancer(state, executorService);
}
use of com.linkedin.d2.balancer.properties.ClusterProperties in project rest.li by linkedin.
the class TestD2Config method testPartitionAccessorFactoryWithEmptyClassList.
// Test PartitionAccessorFactory: empty ClassList
@Test
public static void testPartitionAccessorFactoryWithEmptyClassList() throws IOException, InterruptedException, URISyntaxException, Exception {
@SuppressWarnings("serial") final Map<String, List<String>> clustersData = new HashMap<String, List<String>>() {
{
put("partitioned-cluster", Arrays.asList(new String[] { "partitioned-service-1", "partitioned-service-2" }));
}
};
final Map<String, Object> partitionProperties = new HashMap<>();
Map<String, Object> customized = new HashMap<>();
List<String> classList = Collections.emptyList();
customized.put("partitionType", "CUSTOM");
customized.put("partitionCount", "10");
customized.put("partitionAccessorList", classList);
partitionProperties.put("partitionProperties", customized);
final PartitionAccessorRegistry registry = new PartitionAccessorRegistry() {
private final Map<String, List<BasePartitionAccessor>> _registry = new HashMap<>();
@Override
public void register(String clusterName, BasePartitionAccessor accessor) {
List<BasePartitionAccessor> accessors = _registry.computeIfAbsent(clusterName, k -> new ArrayList<>());
accessors.add(accessor);
}
@Override
public List<BasePartitionAccessor> getPartitionAccessors(String clusterName) {
return _registry.get(clusterName);
}
};
class TestPartitionAccessor1 implements PartitionAccessor {
@Override
public int getPartitionId(URI uri) throws PartitionAccessException {
return testGetPartitionId(uri);
}
@Override
public int getMaxPartitionId() {
return 10;
}
}
;
class TestPartitionAccessor2 implements PartitionAccessor {
@Override
public int getPartitionId(URI uri) throws PartitionAccessException {
return 8;
}
@Override
public int getMaxPartitionId() {
return 10;
}
}
;
PartitionAccessor testAccessor1 = new TestPartitionAccessor1();
PartitionAccessor testAccessor2 = new TestPartitionAccessor2();
registry.register("partitioned-cluster", DefaultPartitionAccessor.getInstance());
registry.register("partitioned-cluster", testAccessor1);
registry.register("partitioned-cluster", testAccessor2);
D2ConfigTestUtil d2Conf = new D2ConfigTestUtil(clustersData, partitionProperties);
assertEquals(d2Conf.runDiscovery(_zkHosts), 0);
verifyPartitionProperties("partitioned-cluster", partitionProperties);
final ClusterProperties clusterprops = getClusterProperties(_zkclient, "partitioned-cluster");
final PartitionAccessor accessor = PartitionAccessorFactory.getPartitionAccessor("partitioned-cluster", registry, clusterprops.getPartitionProperties());
final String legalUri1 = "/profiles?field=position&id=100";
final String legalUri2 = "/cap?wid=99&id=176&randid=301";
final String legalUri3 = "/seas?id=3324";
final String illegalUri = "/?id=1000000000000000000000000000000000000000000000111111111";
assertEquals(0, accessor.getPartitionId(URI.create(legalUri1)));
assertEquals(0, accessor.getPartitionId(URI.create(legalUri2)));
assertEquals(0, accessor.getPartitionId(URI.create(legalUri3)));
assertEquals(0, accessor.getPartitionId(URI.create(illegalUri)));
}
Aggregations