use of com.linkedin.d2.balancer.strategies.relative.PartitionState in project rest.li by linkedin.
the class StateUpdaterTest method testHealthScoreDrop.
@Test(dataProvider = "trackerClients")
public void testHealthScoreDrop(List<TrackerClient> trackerClients, double highLatencyFactor, double highErrorRate, boolean expectToDropHealthScore) {
PartitionState state = new PartitionStateTestDataBuilder().setClusterGenerationId(DEFAULT_CLUSTER_GENERATION_ID).setTrackerClientStateMap(trackerClients, Arrays.asList(StateUpdater.MAX_HEALTH_SCORE, StateUpdater.MAX_HEALTH_SCORE, StateUpdater.MAX_HEALTH_SCORE), 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().setRelativeLatencyHighThresholdFactor(highLatencyFactor).setHighErrorRate(highErrorRate), partitionLoadBalancerStateMap);
_stateUpdater.updateState();
Map<URI, Integer> pointsMap = _stateUpdater.getPointsMap(DEFAULT_PARTITION_ID);
if (!expectToDropHealthScore) {
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(), HEALTHY_POINTS);
} else {
assertEquals(pointsMap.get(trackerClients.get(0).getUri()).intValue(), (int) (HEALTHY_POINTS - RelativeLoadBalancerStrategyFactory.DEFAULT_DOWN_STEP * RelativeLoadBalancerStrategyFactory.DEFAULT_POINTS_PER_WEIGHT));
assertEquals(pointsMap.get(trackerClients.get(1).getUri()).intValue(), HEALTHY_POINTS);
assertEquals(pointsMap.get(trackerClients.get(2).getUri()).intValue(), HEALTHY_POINTS);
}
}
use of com.linkedin.d2.balancer.strategies.relative.PartitionState in project rest.li by linkedin.
the class StateUpdaterTest method testClusterUrisChange.
@Test
public void testClusterUrisChange() {
List<TrackerClient> trackerClients = TrackerClientMockHelper.mockTrackerClients(3, Arrays.asList(20, 20, 20), Arrays.asList(10, 10, 10), Arrays.asList(200L, 220L, 1000L), Arrays.asList(100L, 110L, 500L), Arrays.asList(0, 0, 0));
PartitionState state = new PartitionStateTestDataBuilder().setClusterGenerationId(DEFAULT_CLUSTER_GENERATION_ID).setTrackerClientStateMap(trackerClients, Arrays.asList(StateUpdater.MAX_HEALTH_SCORE, StateUpdater.MAX_HEALTH_SCORE, StateUpdater.MAX_HEALTH_SCORE), 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);
// New tracker clients set only contains 2 out of 3 tracker clients from the old state
Set<TrackerClient> newTrackerClientSet = new HashSet<>();
newTrackerClientSet.add(trackerClients.get(0));
newTrackerClientSet.add(trackerClients.get(1));
_stateUpdater.updateStateForPartition(newTrackerClientSet, DEFAULT_PARTITION_ID, state, 1L, false);
Map<URI, Integer> pointsMap = _stateUpdater.getPointsMap(DEFAULT_PARTITION_ID);
assertEquals(pointsMap.size(), 2, "There should only be 2 uris after cluster id change");
assertEquals(pointsMap.get(trackerClients.get(0).getUri()).intValue(), HEALTHY_POINTS);
assertEquals(pointsMap.get(trackerClients.get(1).getUri()).intValue(), HEALTHY_POINTS);
}
use of com.linkedin.d2.balancer.strategies.relative.PartitionState in project rest.li by linkedin.
the class StateUpdaterTest method testUpdateTrackerClientWithDoNotLoadBalance.
@Test
public void testUpdateTrackerClientWithDoNotLoadBalance() {
final boolean doNotLoadBalance = true;
List<TrackerClient> trackerClients = TrackerClientMockHelper.mockTrackerClients(3, Arrays.asList(20, 1, 20), Arrays.asList(0, 0, 0), Arrays.asList(1000L, 5000L, 100000L), Arrays.asList(0L, 0L, 0L), Arrays.asList(0, 0, 10), Arrays.asList(false, false, doNotLoadBalance));
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, "Healthy client should not have health score reduced.");
assertEquals(pointsMap.get(trackerClients.get(1).getUri()).intValue(), (int) (HEALTHY_POINTS - RelativeLoadBalancerStrategyFactory.DEFAULT_DOWN_STEP * RelativeLoadBalancerStrategyFactory.DEFAULT_POINTS_PER_WEIGHT), "This should be considered unhealthy because its latency exceeds the threshold " + "(the client with load balancing disabled should not affect the average latency calculation).");
assertEquals(pointsMap.get(trackerClients.get(2).getUri()).intValue(), HEALTHY_POINTS, "The client with load balancing disabled " + "should not have health score reduced.");
}
use of com.linkedin.d2.balancer.strategies.relative.PartitionState in project rest.li by linkedin.
the class QuarantineManager method enrollNewQuarantineAndRecovery.
/**
* Enroll new tracker client to quarantine or recovery state
*
* @param newPartitionState The new state of the partition
* @param oldPartitionState The old state of the partition
* @param quarantineLatency The latency threshold for D2 quarantine
*/
private void enrollNewQuarantineAndRecovery(PartitionState newPartitionState, PartitionState oldPartitionState, long quarantineLatency, long currentTime) {
int partitionId = newPartitionState.getPartitionId();
Map<TrackerClient, LoadBalancerQuarantine> quarantineMap = newPartitionState.getQuarantineMap();
Map<TrackerClient, LoadBalancerQuarantine> quarantineHistory = newPartitionState.getQuarantineHistory();
Set<TrackerClient> recoverySet = newPartitionState.getRecoveryTrackerClients();
for (TrackerClient trackerClient : newPartitionState.getTrackerClients()) {
TrackerClientState trackerClientState = newPartitionState.getTrackerClientStateMap().get(trackerClient);
double serverWeight = trackerClient.getPartitionWeight(partitionId);
// Check and enroll quarantine map
boolean isQuarantined = enrollClientInQuarantineMap(trackerClient, trackerClientState, serverWeight, quarantineMap, quarantineHistory, newPartitionState.getTrackerClientStateMap().size(), quarantineLatency, currentTime);
if (!isQuarantined) {
if (!_fastRecoveryEnabled) {
performNormalRecovery(trackerClientState);
} else {
// Only enroll the client into recovery state if fast recovery is enabled
enrollSingleClientInRecoverySet(trackerClient, trackerClientState, serverWeight, recoverySet, oldPartitionState);
}
}
}
}
use of com.linkedin.d2.balancer.strategies.relative.PartitionState in project rest.li by linkedin.
the class StateUpdater method updateBaseHealthScoreAndState.
/**
* Update the health score of all tracker clients for the service
*/
private void updateBaseHealthScoreAndState(Set<TrackerClient> trackerClients, PartitionState partitionState, long clusterAvgLatency, boolean clusterUpdated, Map<TrackerClient, CallTracker.CallStats> lastCallStatsMap) {
// Calculate the base health score before we override them when handling the quarantine and recovery
calculateBaseHealthScore(trackerClients, partitionState, clusterAvgLatency, lastCallStatsMap);
// Remove the trackerClients from original map if there is any change in uri list
Map<TrackerClient, TrackerClientState> trackerClientStateMap = partitionState.getTrackerClientStateMap();
if (clusterUpdated) {
List<TrackerClient> trackerClientsToRemove = trackerClientStateMap.keySet().stream().filter(oldTrackerClient -> !trackerClients.contains(oldTrackerClient)).collect(Collectors.toList());
for (TrackerClient trackerClient : trackerClientsToRemove) {
partitionState.removeTrackerClient(trackerClient);
}
}
}
Aggregations