Ribbon 主要是客户端的负载均衡,即服务消费者将注册信息从Eureka集群中获取,缓存在本地,将调用服务对应的服务主机列表拿到,轮询或者随机调用等负载均衡算法,从而进行对同一服务的不同主机进行调用。
Nginx 是客户端的所有请求都交给Nginx ,又nginx进行统一的分发。
有一种说法是:Nginx是集中式的LB而Ribbon是消费者进程内所做的LB。Ribbon 与Eureka server 结合后,工作流程主要
1、选择同一区域内负载较少的Server.
2、通过Server选择服务对应的实例。
从源码查看RoundRobin想到的?那就是自旋锁!
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) {
List<Server> reachableServers = lb.getReachableServers();
List<Server> allServers = lb.getAllServers();
int upCount = reachableServers.size();
int serverCount = allServers.size();
if (upCount != 0 && serverCount != 0) {
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;
}
}
}
incrementAndGetModulo 代码
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;
}