use of com.linkedin.util.clock.Clock in project rest.li by linkedin.
the class SimpleLoadBalancerState method refreshTransportClientsPerService.
void refreshTransportClientsPerService(ServiceProperties serviceProperties) {
String serviceName = serviceProperties.getServiceName();
//create new TransportClients
Map<String, TransportClient> newTransportClients = createAndInsertTransportClientTo(serviceProperties);
// clients-by-scheme map is never edited, only replaced.
newTransportClients = Collections.unmodifiableMap(newTransportClients);
final Map<String, TransportClient> oldTransportClients = _serviceClients.put(serviceName, newTransportClients);
// gets the information for configuring the parameter for how DegraderImpl should behave for
// each tracker clients that we instantiate here. If there's no such information, then we'll instantiate
// each tracker clients with default configuration
DegraderImpl.Config config = null;
if (serviceProperties.getDegraderProperties() != null && !serviceProperties.getDegraderProperties().isEmpty()) {
config = DegraderConfigFactory.toDegraderConfig(serviceProperties.getDegraderProperties());
} else {
debug(_log, "trying to see if there's a special degraderImpl properties but serviceInfo.getDegraderImpl() is null" + " for service name = " + serviceName + " so we'll set config to default");
}
Clock clk = SystemClock.instance();
if (serviceProperties.getLoadBalancerStrategyProperties() != null) {
Map<String, Object> loadBalancerStrategyProperties = serviceProperties.getLoadBalancerStrategyProperties();
clk = MapUtil.getWithDefault(loadBalancerStrategyProperties, PropertyKeys.CLOCK, SystemClock.instance(), Clock.class);
}
Map<URI, TrackerClient> newTrackerClients;
// update all tracker clients to use new configs
LoadBalancerStateItem<UriProperties> uriItem = _uriProperties.get(serviceProperties.getClusterName());
UriProperties uriProperties = uriItem == null ? null : uriItem.getProperty();
if (uriProperties != null) {
Set<URI> uris = uriProperties.Uris();
// clients-by-uri map may be edited later by UriPropertiesListener.handlePut
newTrackerClients = new ConcurrentHashMap<URI, TrackerClient>(CollectionUtils.getMapInitialCapacity(uris.size(), 0.75f), 0.75f, 1);
long trackerClientInterval = getTrackerClientInterval(serviceProperties);
String errorStatusPattern = getErrorStatusPattern(serviceProperties);
for (URI uri : uris) {
TrackerClient trackerClient = getTrackerClient(serviceName, uri, uriProperties.getPartitionDataMap(uri), config, clk, trackerClientInterval, errorStatusPattern);
if (trackerClient != null) {
newTrackerClients.put(uri, trackerClient);
}
}
} else {
// clients-by-uri map may be edited later by UriPropertiesListener.handlePut
newTrackerClients = new ConcurrentHashMap<URI, TrackerClient>(16, 0.75f, 1);
}
//override the oldTrackerClients with newTrackerClients
_trackerClients.put(serviceName, newTrackerClients);
// No need to shut down oldTrackerClients, because they all point directly to the TransportClient for the service
// We do need to shut down the old transport clients
shutdownTransportClients(oldTransportClients, serviceName);
}
use of com.linkedin.util.clock.Clock in project rest.li by linkedin.
the class TrackerClientTest method testClientRestRequest.
@Test(groups = { "small", "back-end" })
public void testClientRestRequest() throws URISyntaxException {
URI uri = URI.create("http://test.qa.com:1234/foo");
double weight = 3d;
TestClient wrappedClient = new TestClient();
Clock clock = new SettableClock();
Map<Integer, PartitionData> partitionDataMap = new HashMap<Integer, PartitionData>(2);
partitionDataMap.put(DefaultPartitionAccessor.DEFAULT_PARTITION_ID, new PartitionData(3d));
TrackerClient client = new TrackerClient(uri, partitionDataMap, wrappedClient, clock, null);
assertEquals(client.getUri(), uri);
Double clientWeight = client.getPartitionWeight(DefaultPartitionAccessor.DEFAULT_PARTITION_ID);
assertEquals(clientWeight, weight);
assertEquals(client.getWrappedClient(), wrappedClient);
RestRequest restRequest = new RestRequestBuilder(uri).build();
Map<String, String> restWireAttrs = new HashMap<String, String>();
TestTransportCallback<RestResponse> restCallback = new TestTransportCallback<RestResponse>();
client.restRequest(restRequest, new RequestContext(), restWireAttrs, restCallback);
assertFalse(restCallback.response.hasError());
assertEquals(wrappedClient.restRequest, restRequest);
assertEquals(wrappedClient.restWireAttrs, restWireAttrs);
}
use of com.linkedin.util.clock.Clock in project rest.li by linkedin.
the class LoadBalancerStrategyBenchmark method createTrackerClients.
private static Map<URI, TrackerClient> createTrackerClients(int numHosts) {
Map<URI, TrackerClient> trackerClients = new HashMap<>();
for (int i = 0; i < numHosts; i++) {
URI uri = URI.create(URI_PREFIX + i + URI_SUFFIX);
trackerClients.put(uri, new TrackerClientImpl(uri, DEFAULT_PARTITION_DATA_MAP, new BaseTransportTestClient(), CLOCK, RelativeLoadBalancerStrategyFactory.DEFAULT_UPDATE_INTERVAL_MS, (status) -> status >= 500 && status <= 599));
}
return trackerClients;
}
use of com.linkedin.util.clock.Clock in project rest.li by linkedin.
the class DegraderLoadBalancerStrategyConfig method createHttpConfigFromMap.
static DegraderLoadBalancerStrategyConfig createHttpConfigFromMap(Map<String, Object> map, HealthCheckOperations healthCheckOperations, ScheduledExecutorService overrideExecutorService, Map<String, String> degraderProperties, EventEmitter emitter) {
Clock clock = MapUtil.getWithDefault(map, PropertyKeys.CLOCK, DEFAULT_CLOCK, Clock.class);
Long updateIntervalMs = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_STRATEGY_PROPERTIES_UPDATE_INTERVAL_MS, DEFAULT_UPDATE_INTERVAL_MS, Long.class);
Boolean updateOnlyAtInterval = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_STRATEGY_PROPERTIES_UPDATE_ONLY_AT_INTERVAL, DEFAULT_UPDATE_ONLY_AT_INTERVAL, Boolean.class);
Integer pointsPerWeight = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_STRATEGY_PROPERTIES_POINTS_PER_WEIGHT, DEFAULT_POINTS_PER_WEIGHT, Integer.class);
String hashMethod = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_HASH_METHOD, null, String.class);
Long minClusterCallCountHighWaterMark = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_CLUSTER_MIN_CALL_COUNT_HIGH_WATER_MARK, DEFAULT_CLUSTER_MIN_CALL_COUNT_HIGH_WATER_MARK, Long.class);
Long minClusterCallCountLowWaterMark = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_CLUSTER_MIN_CALL_COUNT_LOW_WATER_MARK, DEFAULT_CLUSTER_MIN_CALL_COUNT_HIGH_WATER_MARK, Long.class);
Double initialRecoveryLevel = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_INITIAL_RECOVERY_LEVEL, DEFAULT_INITIAL_RECOVERY_LEVEL, Double.class);
Double ringRampFactor = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_RING_RAMP_FACTOR, DEFAULT_RAMP_FACTOR, Double.class);
Double highWaterMark = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_HIGH_WATER_MARK, DEFAULT_HIGH_WATER_MARK, Double.class);
Double lowWaterMark = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_LOW_WATER_MARK, DEFAULT_LOW_WATER_MARK, Double.class);
Double globalStepUp = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_GLOBAL_STEP_UP, DEFAULT_GLOBAL_STEP_UP, Double.class);
Double globalStepDown = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_GLOBAL_STEP_DOWN, DEFAULT_GLOBAL_STEP_DOWN, Double.class);
Object obj = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_HASH_CONFIG, Collections.emptyMap(), Map.class);
// // to appease java 7, which appears to have compilation bugs that cause it to ignore some suppressions, needed to first assign to obj, then assign to the map
@SuppressWarnings("unchecked") Map<String, Object> hashConfig = (Map<String, Object>) obj;
Double hashRingPointCleanUpRate = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_HASHRING_POINT_CLEANUP_RATE, DEFAULT_HASHRING_POINT_CLEANUP_RATE, Double.class);
String consistentHashAlgorithm = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_CONSISTENT_HASH_ALGORITHM, null, String.class);
Integer numProbes = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_CONSISTENT_HASH_NUM_PROBES, DEFAULT_NUM_PROBES);
Integer pointsPerHost = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_CONSISTENT_HASH_POINTS_PER_HOST, DEFAULT_POINTS_PER_HOST);
Double boundedLoadBalancingFactor = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_CONSISTENT_HASH_BOUNDED_LOAD_BALANCING_FACTOR, DEFAULT_BOUNDED_LOAD_BALANCING_FACTOR, Double.class);
String servicePath = MapUtil.getWithDefault(map, PropertyKeys.PATH, null, String.class);
Double quarantineMaxPercent = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_QUARANTINE_MAX_PERCENT, DEFAULT_QUARANTINE_MAXPERCENT, Double.class);
if (quarantineMaxPercent > QUARANTINE_MAXPERCENT_CAP) {
// if the user configures the max percent to a very high value, it can dramatically limit the capacity of the
// cluster when something goes wrong. So impose a cap to max percent.
quarantineMaxPercent = QUARANTINE_MAXPERCENT_CAP;
_log.warn("MaxPercent value {} is too high. Changed it to {}", quarantineMaxPercent, QUARANTINE_MAXPERCENT_CAP);
}
ScheduledExecutorService executorService = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_QUARANTINE_EXECUTOR_SERVICE, null, ScheduledExecutorService.class);
String method = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_QUARANTINE_METHOD, DEFAULT_QUARANTINE_METHOD, String.class);
// lowLatency reflects the expected health threshold for the service so we can use this value as the
// quarantine health checking latency.
Long quarantineLatency = (degraderProperties == null) ? DegraderImpl.DEFAULT_LOW_LATENCY : MapUtil.getWithDefault(degraderProperties, PropertyKeys.DEGRADER_LOW_LATENCY, DegraderImpl.DEFAULT_LOW_LATENCY, Long.class);
// operations of the service therefore should not take that long
if (quarantineLatency > MAX_QUARANTINE_LATENCY) {
quarantineLatency = MAX_QUARANTINE_LATENCY;
}
// health checking method can be customized from d2config.
// The supported format is "<Restli Method>:<URI path>". Both part are optional.
// If <Restli method> is missing, the default method is 'OPTIONS'. If the <URI path>
// is missing, the service path will be used. For example, "OPTIONS:" and
// "GET:/contextPath/service/resources/1234" are all valid settings. Specifically,
// "GET:/<contextPath>/admin" can be used for admin node health checking, where
// <contextPath> has to match the product-spec.json topology configuration.
String healthCheckMethod = method;
String healthCheckPath = null;
int idx = method.indexOf(':');
if (idx != -1) {
// Currently allows user to specify any method for health checking (including non-idempotent one)
healthCheckMethod = method.substring(0, idx);
healthCheckPath = method.substring(idx + 1);
}
if (healthCheckMethod.isEmpty()) {
healthCheckMethod = DEFAULT_QUARANTINE_METHOD;
}
Long lowEmittingInterval = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_LOW_EVENT_EMITTING_INTERVAL, DEFAULT_LOW_EVENT_EMITTING_INTERVAL, Long.class);
Long highEmittingInterval = MapUtil.getWithDefault(map, PropertyKeys.HTTP_LB_HIGH_EVENT_EMITTING_INTERVAL, DEFAULT_HIGH_EVENT_EMITTING_INTERVAL, Long.class);
final String clusterName = MapUtil.getWithDefault(map, PropertyKeys.CLUSTER_NAME, DEFAULT_CLUSTER_NAME, String.class);
return new DegraderLoadBalancerStrategyConfig(updateIntervalMs, updateOnlyAtInterval, pointsPerWeight, hashMethod, hashConfig, clock, initialRecoveryLevel, ringRampFactor, highWaterMark, lowWaterMark, globalStepUp, globalStepDown, minClusterCallCountHighWaterMark, minClusterCallCountLowWaterMark, hashRingPointCleanUpRate, consistentHashAlgorithm, numProbes, pointsPerHost, boundedLoadBalancingFactor, servicePath, quarantineMaxPercent, overrideExecutorService != null ? overrideExecutorService : executorService, healthCheckOperations, healthCheckMethod, healthCheckPath, quarantineLatency, emitter, lowEmittingInterval, highEmittingInterval, clusterName);
}
use of com.linkedin.util.clock.Clock in project rest.li by linkedin.
the class DegraderTrackerClientTest method testClientRestRequest.
@Test(groups = { "small", "back-end" })
public void testClientRestRequest() throws URISyntaxException {
URI uri = URI.create("http://test.qa.com:1234/foo");
double weight = 3d;
TestClient wrappedClient = new TestClient();
Clock clock = new SettableClock();
Map<Integer, PartitionData> partitionDataMap = createDefaultPartitionData(3d);
DegraderTrackerClient client = new DegraderTrackerClientImpl(uri, partitionDataMap, wrappedClient, clock, null);
Assert.assertEquals(client.getUri(), uri);
Double clientWeight = client.getPartitionWeight(DefaultPartitionAccessor.DEFAULT_PARTITION_ID);
Assert.assertEquals(clientWeight, weight);
Assert.assertEquals(client.getTransportClient(), wrappedClient);
RestRequest restRequest = new RestRequestBuilder(uri).build();
Map<String, String> restWireAttrs = new HashMap<>();
TestTransportCallback<RestResponse> restCallback = new TestTransportCallback<>();
client.restRequest(restRequest, new RequestContext(), restWireAttrs, restCallback);
Assert.assertFalse(restCallback.response.hasError());
Assert.assertEquals(wrappedClient.restRequest, restRequest);
Assert.assertEquals(wrappedClient.restWireAttrs, restWireAttrs);
}
Aggregations