use of com.linkedin.d2.balancer.ServiceUnavailableException in project rest.li by linkedin.
the class SimpleLoadBalancerTest method testLoadBalancerDropRate.
/**
* This test simulates dropping requests by playing with OverrideDropRate in config
*
*/
@Test(groups = { "small", "back-end" })
public void testLoadBalancerDropRate() throws ServiceUnavailableException, ExecutionException, InterruptedException {
final int RETRY = 10;
for (int tryAgain = 0; tryAgain < RETRY; ++tryAgain) {
Map<String, LoadBalancerStrategyFactory<? extends LoadBalancerStrategy>> loadBalancerStrategyFactories = new HashMap<String, LoadBalancerStrategyFactory<? extends LoadBalancerStrategy>>();
Map<String, TransportClientFactory> clientFactories = new HashMap<String, TransportClientFactory>();
List<String> prioritizedSchemes = new ArrayList<String>();
MockStore<ServiceProperties> serviceRegistry = new MockStore<ServiceProperties>();
MockStore<ClusterProperties> clusterRegistry = new MockStore<ClusterProperties>();
MockStore<UriProperties> uriRegistry = new MockStore<UriProperties>();
ScheduledExecutorService executorService = new SynchronousExecutorService();
//loadBalancerStrategyFactories.put("rr", new RandomLoadBalancerStrategyFactory());
loadBalancerStrategyFactories.put("degrader", new DegraderLoadBalancerStrategyFactoryV3());
// PrpcClientFactory();
// new
clientFactories.put("http", new DoNothingClientFactory());
// HttpClientFactory();
SimpleLoadBalancerState state = new SimpleLoadBalancerState(executorService, uriRegistry, clusterRegistry, serviceRegistry, clientFactories, loadBalancerStrategyFactories);
SimpleLoadBalancer loadBalancer = new SimpleLoadBalancer(state, 5, TimeUnit.SECONDS);
FutureCallback<None> balancerCallback = new FutureCallback<None>();
loadBalancer.start(balancerCallback);
balancerCallback.get();
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);
prioritizedSchemes.add("http");
clusterRegistry.put("cluster-1", new ClusterProperties("cluster-1"));
serviceRegistry.put("foo", new ServiceProperties("foo", "cluster-1", "/foo", Arrays.asList("degrader"), Collections.<String, Object>emptyMap(), null, null, prioritizedSchemes, null));
uriRegistry.put("cluster-1", new UriProperties("cluster-1", uriData));
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");
Set<URI> expectedUris = new HashSet<URI>();
expectedUris.add(expectedUri1);
expectedUris.add(expectedUri2);
expectedUris.add(expectedUri3);
Random random = new Random();
for (int i = 0; i < 100; ++i) {
try {
RewriteClient client = (RewriteClient) loadBalancer.getClient(new URIRequest("d2://foo/52"), new RequestContext());
TrackerClient tClient = (TrackerClient) client.getWrappedClient();
DegraderImpl degrader = (DegraderImpl) tClient.getDegrader(DefaultPartitionAccessor.DEFAULT_PARTITION_ID);
DegraderImpl.Config cfg = new DegraderImpl.Config(degrader.getConfig());
// Change DropRate to 0.0 at the rate of 1/3
cfg.setOverrideDropRate((random.nextInt(2) == 0) ? 1.0 : 0.0);
degrader.setConfig(cfg);
assertTrue(expectedUris.contains(client.getUri()));
assertEquals(client.getUri().getScheme(), "http");
} catch (ServiceUnavailableException e) {
assertTrue(e.toString().contains("in a bad state (high latency/high error)"));
}
}
final CountDownLatch latch = new CountDownLatch(1);
PropertyEventShutdownCallback callback = new PropertyEventShutdownCallback() {
@Override
public void done() {
latch.countDown();
}
};
state.shutdown(callback);
if (!latch.await(60, TimeUnit.SECONDS)) {
fail("unable to shutdown state");
}
executorService.shutdownNow();
assertTrue(executorService.isShutdown(), "ExecutorService should have shut down!");
}
}
use of com.linkedin.d2.balancer.ServiceUnavailableException in project rest.li by linkedin.
the class SimpleLoadBalancerTest method testLoadBalancerSimulationRandom.
@Test(groups = { "medium", "back-end" }, enabled = false)
public void testLoadBalancerSimulationRandom() throws URISyntaxException, IOException, ServiceUnavailableException, InterruptedException {
SimpleLoadBalancerSimulation simulator = new SimpleLoadBalancerSimulation(new RandomLoadBalancerStrategyFactory());
simulator.simulateMultithreaded(1, 1000, 20);
simulator.reset();
simulator.simulateMultithreaded(50, 10000, 20);
simulator.reset();
}
use of com.linkedin.d2.balancer.ServiceUnavailableException in project rest.li by linkedin.
the class LoadBalancerSimulator method getPoints.
/**
* Given a serviceName and partition number, return the hashring points for each URI
* @param serviceName
* @param partition
* @return
* @throws ServiceUnavailableException
*/
public Map<URI, Integer> getPoints(String serviceName, int partition) throws ServiceUnavailableException {
URI serviceUri = URI.create("d2://" + serviceName);
Ring<URI> ring = _loadBalancer.getRings(serviceUri).get(partition);
Map<URI, Integer> pointsMap = new HashMap<>();
Iterator<URI> iter = ring.getIterator(0);
iter.forEachRemaining(uri -> pointsMap.compute(uri, (k, v) -> v == null ? 1 : v + 1));
return pointsMap;
}
use of com.linkedin.d2.balancer.ServiceUnavailableException in project rest.li by linkedin.
the class SimpleLoadBalancerSimulation method simulateMultithreaded.
/**
* Run the simulation from a play-back text file. The format of the text file is the
* same as the way the random messages are generated in getRandomMessage().
*
* @param threads
* Number of threads to run.
* @param simulationStepSize
* Number of operations to perform during each step.
* @param playbackStream
* The input stream of messages to play back.
* @throws IOException
* @throws ServiceUnavailableException
*/
public void simulateMultithreaded(int threads, int simulationStepSize, InputStream playbackStream) throws IOException, ServiceUnavailableException {
BufferedReader br = new BufferedReader(new InputStreamReader(playbackStream));
String line = "";
initQueues(threads);
int lineCount = 0;
while (line != null) {
// load simulation steps into queue
for (int i = 0; i < simulationStepSize && line != null; ++i) {
line = br.readLine();
if (line != null) {
lineCount++;
String[] message = line.split(" ");
_queues[getThreadId(message, threads)].add(message);
}
}
// simulate
runSimulation(threads);
// now validate that state is as we expect
verifyState();
reset();
}
try {
final CountDownLatch latch = new CountDownLatch(1);
PropertyEventShutdownCallback callback = new PropertyEventShutdownCallback() {
@Override
public void done() {
latch.countDown();
}
};
_state.shutdown(callback);
if (!latch.await(60, TimeUnit.SECONDS)) {
fail("unable to shutdown state");
}
} catch (InterruptedException e) {
fail("unable to shutdown");
}
}
use of com.linkedin.d2.balancer.ServiceUnavailableException in project rest.li by linkedin.
the class SimpleLoadBalancerSimulation method simulateMultithreaded.
/**
* Run the simulation using randomly generated messages.
*
* @param threads
* Number of threads to run.
* @param simulationStepSize
* Number of operations to perform during each step.
* @param totalSteps
* The number of steps.
* @throws ServiceUnavailableException
*/
public void simulateMultithreaded(int threads, int simulationStepSize, int totalSteps, String messageLogPath) throws ServiceUnavailableException {
initQueues(threads);
initMessageLog(messageLogPath);
for (int step = 0; step < totalSteps; ++step) {
try {
// load simulation steps into queue
for (int i = 0; i < simulationStepSize; ++i) {
String[] message = getRandomMessage();
if (_messageLog != null) {
_messageLog.write((LoadBalancerUtil.join(Arrays.asList(message), " ") + "\n").getBytes("UTF-8"));
}
_queues[getThreadId(message, threads)].add(message);
++_totalMessages;
}
} catch (UnsupportedEncodingException e) {
fail("unable to encode message properly");
} catch (IOException e) {
fail("unable to write to file");
}
// simulate
long start = System.currentTimeMillis();
runSimulation(threads);
System.err.println(simulationStepSize + " in " + (System.currentTimeMillis() - start) + "ms (" + _totalMessages + " total)");
// now validate that state is as we expect
verifyState();
reset();
}
try {
final CountDownLatch latch = new CountDownLatch(1);
PropertyEventShutdownCallback callback = new PropertyEventShutdownCallback() {
@Override
public void done() {
latch.countDown();
}
};
_state.shutdown(callback);
if (!latch.await(60, TimeUnit.SECONDS)) {
fail("unable to shutdown state");
}
} catch (InterruptedException e) {
fail("interrupted during state and thread shutdown");
}
}
Aggregations