/*
*
* Copyright 2013 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.netflix.loadbalancer;
import static org.junit.Assert.*;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.AfterClass;
import org.junit.Test;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.netflix.config.ConfigurationManager;
import com.netflix.config.DeploymentContext.ContextKey;
public class PredicatesTest {
static {
ConfigurationManager.getConfigInstance().setProperty("niws.loadbalancer.default.circuitTripTimeoutFactorSeconds", 100000);
ConfigurationManager.getConfigInstance().setProperty("niws.loadbalancer.default.circuitTripMaxTimeoutSeconds", 1000000);
}
@AfterClass
public static void cleanup() {
ConfigurationManager.getConfigInstance().clearProperty("niws.loadbalancer.default.circuitTripTimeoutFactorSeconds");
ConfigurationManager.getConfigInstance().clearProperty("niws.loadbalancer.default.circuitTripMaxTimeoutSeconds");
}
public void setServerStats(LoadBalancerStats lbStats, Object[][] stats) {
for (Object[] serverStats: stats) {
Server server = (Server) serverStats[0];
Boolean circuitTripped = (Boolean) serverStats[1];
Integer activeConnections = (Integer) serverStats[2];
ServerStats ss = lbStats.getSingleServerStat(server);
if (circuitTripped) {
for (int i = 0; i < 3; i++) {
ss.incrementSuccessiveConnectionFailureCount();
}
}
for (int i = 0; i < activeConnections; i++) {
ss.incrementActiveRequestsCount();
}
}
}
@Test
public void testAvalabilityPredicate() {
Object[][] stats = new Object[10][3];
List<Server> expectedFiltered = Lists.newArrayList();
for (int i = 0; i < 7; i++) {
stats[i] = new Object[3];
stats[i][0] = new Server("good:" + i);
stats[i][1] = false;
stats[i][2] = 0;
expectedFiltered.add((Server) stats[i][0]);
}
for (int i = 7; i < 10; i++) {
stats[i] = new Object[3];
stats[i][0] = new Server("bad:" + i);
stats[i][1] = true;
stats[i][2] = 0;
}
LoadBalancerStats lbStats = new LoadBalancerStats("default");
setServerStats(lbStats, stats);
AvailabilityPredicate predicate = new AvailabilityPredicate(lbStats, null);
assertFalse(predicate.apply(new PredicateKey((Server) stats[8][0])));
assertTrue(predicate.apply(new PredicateKey((Server) stats[0][0])));
List<Server> servers = Lists.newArrayList();
for (int i = 0; i < 10; i++) {
servers.add((Server) stats[i][0]);
}
List<Server> filtered = predicate.getEligibleServers(servers);
assertEquals(expectedFiltered, filtered);
Set<Server> chosen = Sets.newHashSet();
for (int i = 0; i < 20; i++) {
Server s = predicate.chooseRoundRobinAfterFiltering(servers).get();
assertEquals("good:" + (i % 7), s.getId());
chosen.add(s);
}
assertEquals(7, chosen.size());
}
@Test
public void testZoneAvoidancePredicate() {
Object[][] stats = new Object[10][3];
Map<String, List<Server>> zoneMap = Maps.newHashMap();
List<Server> expectedFiltered = Lists.newArrayList();
List<Server> list0 = Lists.newArrayList();
for (int i = 0; i < 3; i++) {
stats[i] = new Object[3];
stats[i][0] = new Server("good:" + i);
((Server) stats[i][0]).setZone("0");
list0.add((Server) stats[i][0]);
stats[i][1] = false;
stats[i][2] = 0;
expectedFiltered.add((Server) stats[i][0]);
}
zoneMap.put("0", list0);
List<Server> list1 = Lists.newArrayList();
for (int i = 3; i < 7; i++) {
stats[i] = new Object[3];
stats[i][0] = new Server("bad:" + i);
((Server) stats[i][0]).setZone("1");
list1.add((Server) stats[i][0]);
stats[i][1] = false;
stats[i][2] = 2;
}
zoneMap.put("1", list1);
List<Server> list2 = Lists.newArrayList();
for (int i = 7; i < 10; i++) {
stats[i] = new Object[3];
stats[i][0] = new Server("good:" + i);
((Server) stats[i][0]).setZone("2");
list2.add((Server) stats[i][0]);
stats[i][1] = false;
stats[i][2] = 1;
}
zoneMap.put("2", list2);
LoadBalancerStats lbStats = new LoadBalancerStats("default");
setServerStats(lbStats, stats);
lbStats.updateZoneServerMapping(zoneMap);
ZoneAvoidancePredicate predicate = new ZoneAvoidancePredicate(lbStats, null);
assertFalse(predicate.apply(new PredicateKey((Server) stats[5][0])));
assertTrue(predicate.apply(new PredicateKey((Server) stats[0][0])));
assertTrue(predicate.apply(new PredicateKey((Server) stats[9][0])));
}
@Test
public void testCompositePredicate() {
Object[][] stats = new Object[10][3];
Map<String, List<Server>> zoneMap = Maps.newHashMap();
List<Server> expectedFiltered = Lists.newArrayList();
for (int i = 0; i < 3; i++) {
stats[i] = new Object[3];
stats[i][0] = new Server("good:" + i);
((Server) stats[i][0]).setZone("0");
stats[i][1] = false;
stats[i][2] = 0;
expectedFiltered.add((Server) stats[i][0]);
}
List<Server> list1 = Lists.newArrayList();
for (int i = 3; i < 7; i++) {
stats[i] = new Object[3];
stats[i][0] = new Server("bad:" + i);
((Server) stats[i][0]).setZone("0");
list1.add((Server) stats[i][0]);
stats[i][1] = true;
stats[i][2] = 0;
}
zoneMap.put("1", list1);
List<Server> list2 = Lists.newArrayList();
for (int i = 7; i < 10; i++) {
stats[i] = new Object[3];
stats[i][0] = new Server("good:" + i);
((Server) stats[i][0]).setZone("1");
list2.add((Server) stats[i][0]);
stats[i][1] = false;
stats[i][2] = 0;
}
zoneMap.put("2", list2);
LoadBalancerStats lbStats = new LoadBalancerStats("default");
setServerStats(lbStats, stats);
lbStats.updateZoneServerMapping(zoneMap);
ConfigurationManager.getDeploymentContext().setValue(ContextKey.zone, "0");
AvailabilityPredicate p1 = new AvailabilityPredicate(lbStats, null);
ZoneAffinityPredicate p2 = new ZoneAffinityPredicate();
CompositePredicate c = CompositePredicate.withPredicates(p2, p1).build();
assertFalse(c.apply(new PredicateKey((Server) stats[5][0])));
assertTrue(c.apply(new PredicateKey((Server) stats[0][0])));
assertFalse(c.apply(new PredicateKey((Server) stats[9][0])));
List<Server> servers = Lists.newArrayList();
for (int i = 0; i < 10; i++) {
servers.add((Server) stats[i][0]);
}
List<Server> filtered = c.getEligibleServers(servers);
assertEquals(3, filtered.size());
CompositePredicate c2 = CompositePredicate.withPredicates(p2, p1)
.setFallbackThresholdAsMinimalFilteredNumberOfServers(5)
.addFallbackPredicate(p1).build();
filtered = c2.getEligibleServers(servers);
assertEquals(6, filtered.size());
}
}