use of com.linkedin.d2.balancer.LoadBalancer in project rest.li by linkedin.
the class WarmUpLoadBalancerTest method testMakingWarmUpRequests.
@Test(timeOut = 10000)
public void testMakingWarmUpRequests() throws URISyntaxException, InterruptedException, ExecutionException, TimeoutException {
createDefaultServicesIniFiles();
TestLoadBalancer balancer = new TestLoadBalancer();
AtomicInteger requestCount = balancer.getRequestCount();
LoadBalancer warmUpLoadBalancer = new WarmUpLoadBalancer(balancer, balancer, Executors.newSingleThreadScheduledExecutor(), _tmpdir.getAbsolutePath(), MY_SERVICES_FS, _FSBasedDownstreamServicesFetcher, WarmUpLoadBalancer.DEFAULT_SEND_REQUESTS_TIMEOUT_SECONDS, WarmUpLoadBalancer.DEFAULT_CONCURRENT_REQUESTS);
FutureCallback<None> callback = new FutureCallback<>();
warmUpLoadBalancer.start(callback);
callback.get(5000, TimeUnit.MILLISECONDS);
Assert.assertEquals(VALID_FILES.size(), requestCount.get());
}
use of com.linkedin.d2.balancer.LoadBalancer in project rest.li by linkedin.
the class TestD2ConfigWithSingleZKFailover method setup.
@BeforeTest
public void setup() throws IOException, Exception {
// zkServer
_zkServer = ZKTestUtil.startZKServer();
_zkPort = _zkServer.getPort();
_zkHosts = ZK_HOST + ":" + _zkPort;
_zkUriString = "zk://" + _zkHosts;
// Register clusters/services (two services per cluster)
LoadBalancerClientCli.runDiscovery(_zkHosts, "/d2", D2_CONFIG_DATA);
// Get LoadBalancer Client
_cli = new LoadBalancerClientCli(_zkHosts, "/d2");
// Echo servers startup
startAllEchoServers();
assertAllEchoServersRunning(_echoServers);
_client = _cli.createClient(_cli.getZKClient(), _zkUriString, "/d2", "service-1_1");
_log.info(LoadBalancerClientCli.printStores(_cli.getZKClient(), _zkUriString, "/d2"));
assertAllEchoServersRegistered(_cli.getZKClient(), _zkUriString, _echoServers);
}
use of com.linkedin.d2.balancer.LoadBalancer in project rest.li by linkedin.
the class D2ClientBuilder method build.
/**
* @return {@link D2Client} that is not started yet. Call start(Callback) to start it.
*/
public D2Client build() {
final Map<String, TransportClientFactory> transportClientFactories = (_config.clientFactories == null) ? // if user didn't provide transportClientFactories we'll use default ones
createDefaultTransportClientFactories() : _config.clientFactories;
List<ScheduledExecutorService> executorsToShutDown = new ArrayList<>();
if (_config.startUpExecutorService == null) {
// creating an executor that when there are no tasks to execute doesn't create any thread.
_config.startUpExecutorService = Executors.newScheduledThreadPool(0, new NamedThreadFactory("D2 StartupOnlyExecutor"));
executorsToShutDown.add(_config.startUpExecutorService);
}
if (_config._executorService == null) {
LOG.warn("No executor service passed as argument. Pass it for " + "enhanced monitoring and to have better control over the executor.");
_config._executorService = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("D2 PropertyEventExecutor"));
executorsToShutDown.add(_config._executorService);
}
if (_config.downstreamServicesFetcher == null) {
_config.downstreamServicesFetcher = new FSBasedDownstreamServicesFetcher(_config.fsBasePath, _config.d2ServicePath);
}
if (_config.jmxManager == null) {
_config.jmxManager = new NoOpJmxManager();
}
if (_config.d2ServicePath == null || // checking empty for backward compatibility with ZKFS behavior
_config.d2ServicePath.isEmpty()) {
_config.d2ServicePath = ZKFSUtil.SERVICE_PATH;
}
final Map<String, LoadBalancerStrategyFactory<? extends LoadBalancerStrategy>> loadBalancerStrategyFactories = createDefaultLoadBalancerStrategyFactories();
final D2ClientConfig cfg = new D2ClientConfig(_config.zkHosts, _config.zkSessionTimeoutInMs, _config.zkStartupTimeoutInMs, _config.lbWaitTimeout, _config.lbWaitUnit, _config.flagFile, _config.basePath, _config.fsBasePath, _config.componentFactory, transportClientFactories, _config.lbWithFacilitiesFactory, _config.sslContext, _config.sslParameters, _config.isSSLEnabled, _config.shutdownAsynchronously, _config.isSymlinkAware, _config.clientServicesConfig, _config.d2ServicePath, _config.useNewEphemeralStoreWatcher, _config.healthCheckOperations, _config._executorService, _config.retry, _config.restRetryEnabled, _config.streamRetryEnabled, _config.retryLimit, _config.retryUpdateIntervalMs, _config.retryAggregatedIntervalNum, _config.warmUp, _config.warmUpTimeoutSeconds, _config.warmUpConcurrentRequests, _config.downstreamServicesFetcher, _config.backupRequestsEnabled, _config.backupRequestsStrategyStatsConsumer, _config.backupRequestsLatencyNotificationInterval, _config.backupRequestsLatencyNotificationIntervalUnit, _config.enableBackupRequestsClientAsync, _config._backupRequestsExecutorService, _config.eventEmitter, _config.partitionAccessorRegistry, _config.zooKeeperDecorator, _config.enableSaveUriDataOnDisk, loadBalancerStrategyFactories, _config.requestTimeoutHandlerEnabled, _config.sslSessionValidatorFactory, _config.zkConnectionToUseForLB, _config.startUpExecutorService, _config.jmxManager, _config.d2JmxManagerPrefix, _config.zookeeperReadWindowMs, _config.enableRelativeLoadBalancer, _config.deterministicSubsettingMetadataProvider);
final LoadBalancerWithFacilitiesFactory loadBalancerFactory = (_config.lbWithFacilitiesFactory == null) ? new ZKFSLoadBalancerWithFacilitiesFactory() : _config.lbWithFacilitiesFactory;
LoadBalancerWithFacilities loadBalancer = loadBalancerFactory.create(cfg);
D2Client d2Client = new DynamicClient(loadBalancer, loadBalancer, _restOverStream);
if (_config.requestTimeoutHandlerEnabled) {
d2Client = new RequestTimeoutClient(d2Client, loadBalancer, _config._executorService);
}
if (_config.backupRequestsEnabled) {
ScheduledExecutorService executor = _config._backupRequestsExecutorService;
if (executor == null) {
LOG.warn("Backup Requests Executor not configured, creating one with core pool size equal to: " + Runtime.getRuntime().availableProcessors());
executor = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(), new NamedThreadFactory("Backup Requests Executor"));
executorsToShutDown.add(executor);
}
d2Client = new BackupRequestsClient(d2Client, loadBalancer, executor, _config.backupRequestsStrategyStatsConsumer, _config.backupRequestsLatencyNotificationInterval, _config.backupRequestsLatencyNotificationIntervalUnit, _config.enableBackupRequestsClientAsync);
}
if (_config.retry) {
d2Client = new RetryClient(d2Client, loadBalancer, _config.retryLimit, _config.retryUpdateIntervalMs, _config.retryAggregatedIntervalNum, SystemClock.instance(), true, true);
} else if (_config.restRetryEnabled || _config.streamRetryEnabled) {
d2Client = new RetryClient(d2Client, loadBalancer, _config.retryLimit, _config.retryUpdateIntervalMs, _config.retryAggregatedIntervalNum, SystemClock.instance(), _config.restRetryEnabled, _config.streamRetryEnabled);
}
// is being shut down.
if (_config.clientFactories != transportClientFactories) {
d2Client = new TransportClientFactoryAwareD2Client(d2Client, transportClientFactories.values());
}
if (executorsToShutDown.size() > 0) {
d2Client = new ExecutorShutdownAwareD2Client(d2Client, executorsToShutDown);
}
return d2Client;
}
use of com.linkedin.d2.balancer.LoadBalancer in project rest.li by linkedin.
the class TestBackupRequestsClient method createAlwaysBackupClientWithHosts.
private BackupRequestsClient createAlwaysBackupClientWithHosts(List<String> uris, Deque<URI> hostsReceivingRequestList, int responseDelayNano, int backupDelayNano, boolean isD2Async) throws IOException {
Map<URI, Map<Integer, PartitionData>> partitionDescriptions = new HashMap<>();
uris.forEach(uri -> partitionDescriptions.put(URI.create(uri), Collections.singletonMap(0, new PartitionData(1))));
StaticLoadBalancerState LbState = new StaticLoadBalancerState() {
@Override
public TrackerClient getClient(String serviceName, URI uri) {
return new DegraderTrackerClientImpl(uri, partitionDescriptions.get(uri), null, SystemClock.instance(), null) {
@Override
public void restRequest(RestRequest request, RequestContext requestContext, Map<String, String> wireAttrs, TransportCallback<RestResponse> callback) {
// whenever a trackerClient is used to make request, record down it's hostname
hostsReceivingRequestList.add(uri);
// delay response to allow backup request to happen
_executor.schedule(() -> callback.onResponse(TransportResponseImpl.success(new RestResponseBuilder().build())), responseDelayNano, TimeUnit.NANOSECONDS);
}
@Override
public void streamRequest(StreamRequest request, RequestContext requestContext, Map<String, String> wireAttrs, TransportCallback<StreamResponse> callback) {
// whenever a trackerClient is used to make request, record down it's hostname
hostsReceivingRequestList.add(uri);
if (null != requestContext.getLocalAttr(R2Constants.BACKUP_REQUEST_BUFFERED_BODY)) {
callback.onResponse(TransportResponseImpl.success(new StreamResponseBuilder().setHeader(BUFFERED_HEADER, String.valueOf(requestContext.getLocalAttr(R2Constants.BACKUP_REQUEST_BUFFERED_BODY) != null)).build(EntityStreams.emptyStream())));
return;
}
request.getEntityStream().setReader(new DrainReader() {
public void onDone() {
// delay response to allow backup request to happen
_executor.schedule(() -> callback.onResponse(TransportResponseImpl.success(new StreamResponseBuilder().setHeader(BUFFERED_HEADER, String.valueOf(requestContext.getLocalAttr(R2Constants.BACKUP_REQUEST_BUFFERED_BODY) != null)).build(EntityStreams.emptyStream()))), responseDelayNano, TimeUnit.NANOSECONDS);
}
});
}
};
}
};
LbState.TEST_URIS_PARTITIONDESCRIPTIONS.putAll(partitionDescriptions);
LbState.TEST_SERVICE_BACKUP_REQUEST_PROPERTIES.add(createBackupRequestsConfiguration(5, "get"));
LbState.refreshDefaultProperties();
LoadBalancer loadBalancer = new SimpleLoadBalancer(LbState, _executor);
DynamicClient dynamicClient = new DynamicClient(loadBalancer, null);
return new BackupRequestsClient(dynamicClient, loadBalancer, _executor, null, 10, TimeUnit.SECONDS, isD2Async) {
@Override
Optional<TrackingBackupRequestsStrategy> getStrategyAfterUpdate(final String serviceName, final String operation) {
// constantly enable backup request after backupDelayNano time.
BackupRequestsStrategy alwaysBackup = new TestTrackingBackupRequestsStrategy.MockBackupRequestsStrategy(() -> Optional.of((long) backupDelayNano), () -> true);
return Optional.of(new TrackingBackupRequestsStrategy(alwaysBackup));
}
};
}
use of com.linkedin.d2.balancer.LoadBalancer in project rest.li by linkedin.
the class TestBackupRequestsClient method testD2ServiceUnavailable.
@Test(dataProvider = "isD2Async")
public void testD2ServiceUnavailable(boolean isD2Async) throws Exception {
LoadBalancer loadBalancer = new TestLoadBalancer(new ConstantResponseTimeDistribution(1, TimeUnit.NANOSECONDS), null, new ServiceUnavailableException("", ""));
TestBackupRequestsStrategyStatsConsumer statsConsumer = new TestBackupRequestsStrategyStatsConsumer();
BackupRequestsClient client = createClient(statsConsumer, loadBalancer, isD2Async);
URI uri = URI.create("d2://testService");
RestRequest restRequest = new RestRequestBuilder(uri).setEntity(CONTENT).build();
RequestContext requestContext = new RequestContext();
requestContext.putLocalAttr(R2Constants.OPERATION, "get");
Future<RestResponse> response = client.restRequest(restRequest, requestContext);
assertEquals(response.get().getStatus(), 200, "If D2 call fails, we should fallback to request without backup");
List<StatsConsumerEvent> events = statsConsumer.getEvents();
assertEquals(events.size(), 0);
}
Aggregations