一.前文回顾
上一次,:Ribbon源码学习(一) 讨论到LoadBalancerClient.execute,是真正的发送Http请求的类。
OK, 现在开始继续分析LoadBalancerClient
我们可以看到,这个LoadBalancerClient 是个接口
那么我们直接看到对应的实现即可。
分析之前,先铺垫一下知识,我们知道Ribbon的功能就是可以做到服务的负载均衡,权重,随机等调用方法。
然后通过RibbonLoadBalancerClient 服务A发给服务B的http请求进行了封装,走以上的调用策略。
那么,就开始分析RibbonLoadBalancerClient.execute
二.RibbonLoadBalancerClient源码分析
public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) throws IOException {
ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
// 通过策略选择正确的server
Server server = getServer(loadBalancer, hint);
if (server == null) {
throw new IllegalStateException("No instances available for " + serviceId);
}
RibbonServer ribbonServer = new RibbonServer(serviceId, server, isSecure(server,
serviceId), serverIntrospector(serviceId).getMetadata(server));
return execute(serviceId, ribbonServer, request);
}
以上我们可以看到
Server server = getServer(loadBalancer, hint);
上面的代码就是获取到对应的server(也就是真正要调用的服务对象)
你可能会问我,那么server到底又是什么呢?
下面放一张Server 对象的截图
从截图中就可以看到,无非是一些服务的信息属性。
比如port端口, id服务名, appName应用名, appServerGroup app应用组别等等。
在拿到这个server对象之后,就是一波远程调用。
在这里我们可以发现,getServer() 就是ribbon策略的关键,是轮训,随机,权重等等。
事不宜迟,直接进入getServer() 方法。
getServer(ILoadBalancer loadBalancer, Object hint)
protected Server getServer(ILoadBalancer loadBalancer, Object hint) {
if (loadBalancer == null) {
return null;
}
// Use 'default' on a null hint, or just pass it on?
return loadBalancer.chooseServer(hint != null ? hint : "default");
}
之后就是loadBalancer.chooseServer(hint != null ? hint : "default")
顾名思义,选择对应的Server,到这里应该是非常接近真相了。
protected IRule rule = DEFAULT_RULE;
DEFAULE_RULE = new RoundRobinRule();
public Server chooseServer(Object key) {
if (counter == null) {
counter = createCounter();
}
counter.increment();
if (rule == null) {
return null;
} else {
try {
// 通过rule选择对应的策略
return rule.choose(key);
} catch (Exception e) {
logger.warn("LoadBalancer [{}]: Error choosing server for key {}", name, key, e);
return null;
}
}
}
所以我们看到这个rule, 默认的就是RoundRobinRule 轮训的rule.
我们只需要去观察RoundRobinRule类的rule.choose(key) 就够用了
三.RoundRobinRule源码分析
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
log.warn("no load balancer");
return null;
}
Server server = null;
int count = 0;
while (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)) {
log.warn("No up servers available from load balancer: " + lb);
return null;
}
// 这里维护着server遍历的下标
int nextServerIndex = incrementAndGetModulo(serverCount);
// allServers就是所有server的集合
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;
}
这个就很简单了,简单的轮询算法。然后轮询对应的server即可。
轮询算法无非就是维护了一个nextServerIndex索引(记录轮训的下标), servers就是一个服务器的集合。