简单看看其他的一些ribbon支持的负载均衡算法的IRule的源码
(1)RoundRobinRule:系统内置的默认负载均衡规范,直接round robin轮询,从一堆server list中,不断的轮询选择出来一个server,每个server平摊到的这个请求,基本上是平均的
这个算法,说白了是轮询,就是一台接着一台去请求,是按照顺序来的
但是我debug源码时,发现ribbon在做轮询负载均衡时使用的不是RoundRobinRule里边的轮询算法,而是通过 nextIndex.getAndIncrement() % eligible.size() 来取模实现轮询负载。不知道是不是和我的ribbon源码版本有关系,我的版本为ribbon-2.2.2,如果有人知道,还请留言告知!感谢!
public class RoundRobinRule extends AbstractLoadBalancerRule {
//轮询算法
private int incrementAndGetModulo(int modulo) {
for (;;) {
//下一个服务器循环计数器nextServerCyclicCounter默认为0
int current = nextServerCyclicCounter.get();
//modulo为serverCount,即服务列表size,服务总数量
int next = (current + 1) % modulo;
if (nextServerCyclicCounter.compareAndSet(current, next))
return next;
}
}
}
(2)AvailabilityFilteringRule:这个rule就是会考察服务器的可用性
如果3次连接失败,就会等待30秒后再次访问;如果不断失败,那么等待时间会不断边长
如果某个服务器的并发请求太高了,那么会绕过去,不再访问
先用round robin算法,轮询依次选择一台server,如果判断这个server是存活的可用的,如果这台server是不可以访问的,那么就用round robin算法再次选择下一台server,依次循环往复,10次。
public class AvailabilityFilteringRule extends PredicateBasedRule {
@Override
public Server choose(Object key) {
int count = 0;
Server server = roundRobinRule.choose(key);
while (count++ <= 10) {
if (predicate.apply(new PredicateKey(server))) {
return server;
}
server = roundRobinRule.choose(key);
}
return super.choose(key);
}
}
(3)WeightedResponseTimeRule:带着权重的,每个服务器可以有权重,权重越高优先访问,如果某个服务器响应时间比较长,那么权重就会降低,减少访问
public class WeightedResponseTimeRule extends RoundRobinRule {
@Override
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
return null;
}
Server server = null;
while (server == null) {
// get hold of the current reference in case it is changed from the other thread
List<Double> currentWeights = accumulatedWeights;
if (Thread.interrupted()) {
return null;
}
List<Server> allList = lb.getAllServers();
int serverCount = allList.size();
if (serverCount == 0) {
return null;
}
int serverIndex = 0;
// last one in the list is the sum of all weights
double maxTotalWeight = currentWeights.size() == 0 ? 0 : currentWeights.get(currentWeights.size() - 1);
// No server has been hit yet and total weight is not initialized
// fallback to use round robin
if (maxTotalWeight < 0.001d) {
server = super.choose(getLoadBalancer(), key);
if(server == null) {
return server;
}
} else {
// generate a random weight between 0 (inclusive) to maxTotalWeight (exclusive)
double randomWeight = random.nextDouble() * maxTotalWeight;
// pick the server index based on the randomIndex
int n = 0;
for (Double d : currentWeights) {
if (d >= randomWeight) {
serverIndex = n;
break;
} else {
n++;
}
}
server = allList.get(serverIndex);
}
if (server == null) {
/* Transient. */
Thread.yield();
continue;
}
if (server.isAlive()) {
return (server);
}
// Next.
server = null;
}
return server;
}
}
(4)ZoneAvoidanceRule:根据机房和服务器来进行负载均衡,说白了,就是机房的意思,看了源码就是知道了,这个就是所谓的spring cloud ribbon环境中的默认的Rule
public class ZoneAvoidanceRule extends PredicateBasedRule {
static String randomChooseZone(Map<String, ZoneSnapshot> snapshot,
Set<String> chooseFrom) {
if (chooseFrom == null || chooseFrom.size() == 0) {
return null;
}
String selectedZone = chooseFrom.iterator().next();
if (chooseFrom.size() == 1) {
return selectedZone;
}
int totalServerCount = 0;
for (String zone : chooseFrom) {
totalServerCount += snapshot.get(zone).getInstanceCount();
}
int index = random.nextInt(totalServerCount) + 1;
int sum = 0;
for (String zone : chooseFrom) {
sum += snapshot.get(zone).getInstanceCount();
if (index <= sum) {
selectedZone = zone;
break;
}
}
return selectedZone;
}
}
下边几种不常用的IRule就不贴源码了。。。
(5)BestAvailableRule:忽略那些请求失败的服务器,然后尽量找并发比较低的服务器来请求
(6)RandomRule:随机找一个服务器,尽量将流量分散在各个服务器上
(7)RetryRule:可以重试,就是通过round robin找到的服务器请求失败,可以重新找一个服务器