Spring Cloud整合了ribbon作为客户端的负载均衡器,其中提供了一些负载均衡的算法,本文就了解这些负载均衡的实现:
一、负载均衡策略
负载均衡策略的顶层接口为IRule,看下其类结构:
public interface IRule{
public Server choose(Object key);
public void setLoadBalancer(ILoadBalancer lb);
public ILoadBalancer getLoadBalancer();
}
choose(Object key):根据key值从负载均衡器的所有服务列表或存活的服务列表中选择一个存活的服务,这里的key值一般为服务的实例名称。
setLoadBalancer(ILoadBalancer lb):设置一个负载均衡器
getLoadBalancer():获取一个负载均衡器
接下来,我们看下IRule有哪些实现类,每种实现类都表示哪些算法,查看其类图:
AbstractLoadBalancerRule定义了ILoadBalancer实例,通过setLoadBalancer和getLoadBalancer对负载均衡器进行存取;
RoundRobinRule
最著名和最基本的负载平衡策略,即循环规则。
查看核心算法实现的源码:
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
log.warn("no load balancer");
return null;
}
Server server = null;
int count = 0;
//若服务为空,或循环次数<10,这里为10是不怕总数过大一直循环影响性能,循环10次获取的实例都为空则直接结束
while (server == null && count++ < 10) {
List<Server> reachableServers = lb.getReachableServers();
List<Server> allServers = lb.getAllServers();
int upCount = reachableServers.size();
int serverCount = allServers.size();
//若存活的实例数量或总实例数量=0则返回空
if ((upCount == 0) || (serverCount == 0)) {
log.warn("No up servers available from load balancer: " + lb);
return null;
}
//获取实例的下标值
int nextServerIndex = incrementAndGetModulo(serverCount);
server = allServers.get(nextServerIndex);
//若是获取的服务为空,则继续循环
if (server == null) {
/* Transient. */
Thread.yield();
continue;
}
//若实例是生效的
if (server.isAlive() && (server.isReadyToServe())) {
return (server);
}
// Next.
server = null;
}
if (count >= 10) {
log.warn("No available alive servers after 10 tries from load balancer: "
+ lb);
}
return server;
}
private int incrementAndGetModulo(int modulo) {
for (;;) {
int current = nextServer