use of com.linkedin.d2.balancer.clients.TrackerClient in project rest.li by linkedin.
the class StateUpdaterTest method testUpdateOnePartition.
@Test
public void testUpdateOnePartition() {
List<TrackerClient> trackerClients = TrackerClientMockHelper.mockTrackerClients(3, Arrays.asList(20, 20, 20), Arrays.asList(10, 10, 10), Arrays.asList(200L, 300L, 1000L), Arrays.asList(100L, 200L, 500L), Arrays.asList(0, 0, 0));
PartitionState state = new PartitionStateTestDataBuilder().setClusterGenerationId(DEFAULT_CLUSTER_GENERATION_ID).setTrackerClientStateMap(trackerClients, Arrays.asList(1.0, 1.0, 1.0), Arrays.asList(TrackerClientState.HealthState.HEALTHY, TrackerClientState.HealthState.HEALTHY, TrackerClientState.HealthState.HEALTHY), Arrays.asList(30, 30, 30)).build();
ConcurrentMap<Integer, PartitionState> partitionLoadBalancerStateMap = new ConcurrentHashMap<>();
partitionLoadBalancerStateMap.put(DEFAULT_PARTITION_ID, state);
setup(new D2RelativeStrategyProperties(), partitionLoadBalancerStateMap);
_stateUpdater.updateState();
Map<URI, Integer> pointsMap = _stateUpdater.getPointsMap(DEFAULT_PARTITION_ID);
assertEquals(pointsMap.get(trackerClients.get(0).getUri()).intValue(), HEALTHY_POINTS);
assertEquals(pointsMap.get(trackerClients.get(1).getUri()).intValue(), HEALTHY_POINTS);
assertEquals(pointsMap.get(trackerClients.get(2).getUri()).intValue(), (int) (HEALTHY_POINTS - RelativeLoadBalancerStrategyFactory.DEFAULT_DOWN_STEP * RelativeLoadBalancerStrategyFactory.DEFAULT_POINTS_PER_WEIGHT));
}
use of com.linkedin.d2.balancer.clients.TrackerClient in project rest.li by linkedin.
the class StateUpdaterTest method testExecutorSchedule.
@Test
public void testExecutorSchedule() throws InterruptedException {
setup(new D2RelativeStrategyProperties(), new ConcurrentHashMap<>());
List<TrackerClient> trackerClients = TrackerClientMockHelper.mockTrackerClients(2, Arrays.asList(20, 20), Arrays.asList(10, 10), Arrays.asList(200L, 200L), Arrays.asList(100L, 100L), Arrays.asList(0, 0));
PartitionState existingState = new PartitionStateTestDataBuilder().setTrackerClientStateMap(trackerClients, Arrays.asList(1.0, 1.0), Arrays.asList(TrackerClientState.HealthState.HEALTHY, TrackerClientState.HealthState.HEALTHY), Arrays.asList(30, 30)).build();
ConcurrentMap<Integer, PartitionState> stateMap = new ConcurrentHashMap<>();
stateMap.put(DEFAULT_PARTITION_ID, existingState);
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
D2RelativeStrategyProperties relativeStrategyProperties = RelativeLoadBalancerStrategyFactory.putDefaultValues(new D2RelativeStrategyProperties());
_stateUpdater = new StateUpdater(relativeStrategyProperties, _quarantineManager, executorService, stateMap, Collections.emptyList(), SERVICE_NAME);
// In 6 seconds, the update should be executed twice
CountDownLatch countDownLatch = new CountDownLatch(2);
Mockito.doAnswer(new ExecutionCountDown<>(countDownLatch)).when(_quarantineManager).updateQuarantineState(any(), any(), anyLong());
if (!countDownLatch.await(6, TimeUnit.SECONDS)) {
fail("scheduled update failed to finish within 6 seconds");
}
Mockito.verify(_quarantineManager, Mockito.atLeast(2)).updateQuarantineState(any(), any(), anyLong());
assertEquals(_stateUpdater.getPointsMap(DEFAULT_PARTITION_ID).get(trackerClients.get(0).getUri()).intValue(), HEALTHY_POINTS);
assertEquals(_stateUpdater.getPointsMap(DEFAULT_PARTITION_ID).get(trackerClients.get(1).getUri()).intValue(), HEALTHY_POINTS);
executorService.shutdown();
}
use of com.linkedin.d2.balancer.clients.TrackerClient in project rest.li by linkedin.
the class StateUpdaterTest method testExecutorScheduleWithError.
@Test
public void testExecutorScheduleWithError() throws InterruptedException {
D2RelativeStrategyProperties relativeStrategyProperties = new D2RelativeStrategyProperties().setInitialHealthScore(0.01).setUpdateIntervalMs(10);
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("D2 TestExecutor"));
setup(relativeStrategyProperties, new ConcurrentHashMap<>(), executor);
List<TrackerClient> trackerClients = TrackerClientMockHelper.mockTrackerClients(2, Arrays.asList(20, 20), Arrays.asList(10, 10), Arrays.asList(200L, 200L), Arrays.asList(100L, 100L), Arrays.asList(0, 0));
_stateUpdater.updateState(new HashSet<>(trackerClients), 0, DEFAULT_CLUSTER_GENERATION_ID, false);
Mockito.doThrow(new NullPointerException()).when(_quarantineManager).updateQuarantineState(Mockito.any(PartitionState.class), Mockito.any(PartitionState.class), anyLong());
assertEquals(_stateUpdater.getPointsMap(0).get(trackerClients.get(0).getUri()).intValue(), 1);
Thread.sleep(21);
assertEquals(_stateUpdater.getPointsMap(0).get(trackerClients.get(0).getUri()).intValue(), 1, "The points did not change due to the failure in each interval execution");
// Verify that the quarantine manager is invoked in each interval, so the tasks are not cancelled
Mockito.verify(_quarantineManager, Mockito.atLeast(3)).updateQuarantineState(Mockito.any(PartitionState.class), Mockito.any(PartitionState.class), anyLong());
executor.shutdown();
}
use of com.linkedin.d2.balancer.clients.TrackerClient in project rest.li by linkedin.
the class DegraderLoadBalancerTest method testHighLowWatermarks.
@Test(groups = { "small", "back-end" })
public void testHighLowWatermarks() {
final int NUM_CHECKS = 5;
Map<String, Object> myMap = lbDefaultConfig();
Long timeInterval = 5000L;
double globalStepUp = 0.4;
double globalStepDown = 0.4;
double highWaterMark = 1000;
double lowWaterMark = 50;
TestClock clock = new TestClock();
myMap.put(PropertyKeys.CLOCK, clock);
myMap.put(PropertyKeys.HTTP_LB_STRATEGY_PROPERTIES_UPDATE_INTERVAL_MS, timeInterval);
myMap.put(PropertyKeys.HTTP_LB_GLOBAL_STEP_UP, globalStepUp);
myMap.put(PropertyKeys.HTTP_LB_GLOBAL_STEP_DOWN, globalStepDown);
myMap.put(PropertyKeys.HTTP_LB_HIGH_WATER_MARK, highWaterMark);
myMap.put(PropertyKeys.HTTP_LB_LOW_WATER_MARK, lowWaterMark);
myMap.put(PropertyKeys.HTTP_LB_CLUSTER_MIN_CALL_COUNT_HIGH_WATER_MARK, 1l);
myMap.put(PropertyKeys.HTTP_LB_CLUSTER_MIN_CALL_COUNT_LOW_WATER_MARK, 1l);
DegraderLoadBalancerStrategyConfig config = DegraderLoadBalancerStrategyConfig.createHttpConfigFromMap(myMap);
DegraderLoadBalancerStrategyV3 strategy = new DegraderLoadBalancerStrategyV3(config, "DegraderLoadBalancerTest", null, DEGRADER_STATE_LISTENER_FACTORIES);
List<DegraderTrackerClient> clients = new ArrayList<>();
URI uri1 = URI.create("http://test.linkedin.com:3242/fdsaf");
URIRequest request = new URIRequest(uri1);
DegraderTrackerClient client1 = new DegraderTrackerClientImpl(uri1, getDefaultPartitionData(1d), new TestLoadBalancerClient(uri1), clock, null);
clients.add(client1);
DegraderControl dcClient1Default = client1.getDegraderControl(DEFAULT_PARTITION_ID);
dcClient1Default.setOverrideMinCallCount(5);
dcClient1Default.setMinCallCount(5);
List<CallCompletion> ccList = new ArrayList<>();
CallCompletion cc;
TrackerClient resultTC = getTrackerClient(strategy, request, new RequestContext(), 1, clients);
// The override drop rate should be zero at this point.
assertEquals(dcClient1Default.getOverrideDropRate(), 0.0);
// make high latency calls to the tracker client, verify the override drop rate doesn't change
for (int j = 0; j < NUM_CHECKS; j++) {
cc = client1.getCallTracker().startCall();
ccList.add(cc);
}
clock.addMs((long) highWaterMark);
for (Iterator<CallCompletion> iter = ccList.listIterator(); iter.hasNext(); ) {
cc = iter.next();
cc.endCall();
iter.remove();
}
// go to next time interval.
clock.addMs(timeInterval);
// try call dropping on the next updateState
strategy.setStrategy(DEFAULT_PARTITION_ID, PartitionDegraderLoadBalancerState.Strategy.CALL_DROPPING);
resultTC = getTrackerClient(strategy, request, new RequestContext(), 1, clients);
// we now expect that the override drop rate stepped up because updateState
// made that decision.
assertEquals(dcClient1Default.getOverrideDropRate(), globalStepUp);
// make mid latency calls to the tracker client, verify the override drop rate doesn't change
for (int j = 0; j < NUM_CHECKS; j++) {
// need to use client1 because the resultTC may be null
cc = client1.getCallTracker().startCall();
ccList.add(cc);
}
clock.addMs((long) highWaterMark - 1);
for (Iterator<CallCompletion> iter = ccList.listIterator(); iter.hasNext(); ) {
cc = iter.next();
cc.endCall();
iter.remove();
}
// go to next time interval.
clock.addMs(timeInterval);
double previousOverrideDropRate = dcClient1Default.getOverrideDropRate();
// try call dropping on the next updateState
strategy.setStrategy(DEFAULT_PARTITION_ID, PartitionDegraderLoadBalancerState.Strategy.CALL_DROPPING);
resultTC = getTrackerClient(strategy, request, new RequestContext(), 1, clients);
assertEquals(dcClient1Default.getOverrideDropRate(), previousOverrideDropRate);
// make low latency calls to the tracker client, verify the override drop rate decreases
for (int j = 0; j < NUM_CHECKS; j++) {
cc = client1.getCallTracker().startCall();
ccList.add(cc);
}
clock.addMs((long) lowWaterMark);
for (Iterator<CallCompletion> iter = ccList.listIterator(); iter.hasNext(); ) {
cc = iter.next();
cc.endCall();
iter.remove();
}
// go to next time interval.
clock.addMs(timeInterval);
// try Call dropping on this updateState
strategy.setStrategy(DEFAULT_PARTITION_ID, PartitionDegraderLoadBalancerState.Strategy.CALL_DROPPING);
resultTC = getTrackerClient(strategy, request, new RequestContext(), 1, clients);
assertEquals(((DegraderTrackerClient) resultTC).getDegraderControl(DEFAULT_PARTITION_ID).getOverrideDropRate(), 0.0);
}
use of com.linkedin.d2.balancer.clients.TrackerClient in project rest.li by linkedin.
the class SimpleLoadBalancerStateTest method testGetClientAfterServiceMetadataChange.
@Test(groups = { "small", "back-end" })
public void testGetClientAfterServiceMetadataChange() {
reset();
URI uri = URI.create("http://cluster-1/test");
List<String> schemes = new ArrayList<>();
Map<Integer, PartitionData> partitionData = new HashMap<>(1);
partitionData.put(DefaultPartitionAccessor.DEFAULT_PARTITION_ID, new PartitionData(1d));
Map<URI, Map<Integer, PartitionData>> uriData = new HashMap<>();
uriData.put(uri, partitionData);
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));
_serviceRegistry.put("service-1", new ServiceProperties("service-1", "cluster-1", "/test", Arrays.asList("random"), Collections.<String, Object>emptyMap(), null, null, schemes, null));
assertNull(_state.getClient("service-1", uri));
_uriRegistry.put("cluster-1", new UriProperties("cluster-1", uriData));
TrackerClient client = _state.getClient("service-1", uri);
assertNotNull(client);
assertEquals(client.getUri(), uri);
// now we publish an event that tells service-1 changes cluster. Now it's hosted in cluster-2
_serviceRegistry.put("service-1", new ServiceProperties("service-1", "cluster-2", "/test", Arrays.asList("random"), Collections.<String, Object>emptyMap(), null, null, schemes, null));
// this time, since we haven't listened to cluster-2 and there's no uri in cluster-2, we get no client.
assertNull(_state.getClient("service-1", uri));
// we shouldn't be affected by any update to cluster-1 uris because now service-1 listen to cluster-2
_uriRegistry.put("cluster-1", new UriProperties("cluster-1", uriData));
assertNull(_state.getClient("service-1", uri));
// now let's create URI for cluster 2 and make the state listen to cluster_2
_state.listenToCluster("cluster-2", new NullStateListenerCallback());
URI uri2 = URI.create("http://cluster-2/test");
Map<Integer, PartitionData> partitionData2 = new HashMap<>(1);
partitionData2.put(DefaultPartitionAccessor.DEFAULT_PARTITION_ID, new PartitionData(1d));
Map<URI, Map<Integer, PartitionData>> uriData2 = new HashMap<>();
uriData2.put(uri2, partitionData2);
// if we start publishing new event to cluster-2 then we should get trackerClient
_uriRegistry.put("cluster-2", new UriProperties("cluster-2", uriData2));
client = _state.getClient("service-1", uri2);
assertNotNull(client);
assertEquals(client.getUri(), uri2);
// just to make sure that any event from cluster-1 doesn't affect us anymore
_uriRegistry.put("cluster-1", new UriProperties("cluster-1", uriData));
client = _state.getClient("service-1", uri2);
assertNotNull(client);
assertEquals(client.getUri(), uri2);
// if we pass uri from cluster-1, we also get no tracker client
client = _state.getClient("service-1", uri);
assertNull(client);
}
Aggregations