Ribbon负载均衡算法理解以及手写
最近学到springcloud服务注册,正好看看源码,有错误的地方还请大佬指出
RoundRobinRule
算法:rest接口第几次请求%服务器集群总数量=实际调用服务器位置下标
1.下为RoundRobinRule实现类的代码
2.每次选择服务的时候就会调用一次choose方法
3.我会通过注释去解析源码
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
//如果负载均衡为空报错
log.warn("no load balancer");
return null;
} else {
Server server = null;
int count = 0;
while(true) {
if (server == null && count++ < 10) {
//这一步获取可用的服务器,如果可用服务器为0直接return null
List<Server> reachableServers = lb.getReachableServers();
//这一步获取总的服务器,算法中用到
List<Server> allServers = lb.getAllServers();
//这两步获取服务器数量
int upCount = reachableServers.size();
int serverCount = allServers.size();
if (upCount != 0 && serverCount != 0) {
//incrementAndGetModulo()方法太牛了,移步到这个方法下
int nextServerIndex = this.incrementAndGetModulo(serverCount);
//得到下一步的下标,然后取出这个服务
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;
}
if (count >= 10) {
log.warn("No available alive servers after 10 tries from load balancer: " + lb);
}
return server;
}
}
}
//为什么说架构师牛逼hhh
private int incrementAndGetModulo(int modulo) {
int current;
int next;
do {
//这步获得nextServerCyclicCounter的值
//nextServerCyclicCounter是AtomicInteger类型的
current = this.nextServerCyclicCounter.get();
//算法的内容,下一步是当前步加1,然后对总服务数取模
next = (current + 1) % modulo;
//这一步是cas自旋锁,通过自旋而不是直接加锁来保证原子性
/*
* compareAndSet方法,通过比较nextServerCyclicCounter和current值
* 如果相等nextServerCyclicCounter被赋值为next,然后退出循坏
* 如果不相等,就自旋,current又变成nextServerCyclicCounter,知道相等为止
*/
} while(!this.nextServerCyclicCounter.compareAndSet(current, next));
//然后回到原choose
return next;
}
手写一个负载均衡
等周末再写