Ribbon如何实现轮询负载均衡?
Ribbon有哪些常用的负载均衡策略:轮询,随机等等
那常用的轮询是如何实现的呢❓
👀看一下RoundRobinRule的源码:
- 这里维护了一个原子整型
nextServerCyclicCounter
private AtomicInteger nextServerCyclicCounter;
- 一个无参的构造方法,可以很容易的看的出来就是给这个原子整形
nextServerCyclicCounter
赋初值为0
public RoundRobinRule() {
this.nextServerCyclicCounter = new AtomicInteger(0);
}
- 截取choose函数重要部分查看
while(true) {
if (server == null && count++ < 10) {
//这里就是获得可用的结点,也就是保持活跃的所有结点
List<Server> reachableServers = lb.getReachableServers();
//返回所有的结点
List<Server> allServers = lb.getAllServers();
//计算可用服务的大小
int upCount = reachableServers.size();
//计算所有服务的大小
int serverCount = allServers.size();
//这里做个合法判断
if (upCount != 0 && serverCount != 0) {
//然后关键的就是这里怎么计算出下标nextServerIndex
//那就需要看一下这个increamentAndGetMoudle方法
int nextServerIndex = this.incrementAndGetModulo(serverCount)
/**
private int incrementAndGetModulo(int modulo) {
int current;
int next;
do {
//计算出当前的下标是哪个
current = this.nextServerCyclicCounter.get();
//然后当前的下标加一然后再去对服务总数取余得到下一个下标
next = (current + 1) % modulo;
//这里退出while时做一个原子操作,
} while(!this.nextServerCyclicCounter.compareAndSet(current, next));
return next;
}
*/
//根据这个下标找到集群中具体是哪个服务
server = (Server)allServers.get(nextServerIndex);
//这里为什么会为空有待研究,初步认为服务可能过久没有发送心跳包被剔除了
if (server == null) {
Thread.yield();
} else {
//判断这个服务是否可用可用就返回不可用就继续循环
if (server.isAlive() && server.isReadyToServe()) {
return server;
}
server = null;
}
continue;
}
log.warn("No up servers available from load balancer: " + lb);
return null;
}
//这里这个count是用来记录重试次数的超过10次就会记录仪一条日志不再重试
if (count >= 10) {
log.warn("No available alive servers after 10 tries from load balancer: " + lb);
}
return server;
}