Ribbon的负载均衡入口
关于 Ribbon 的使用的内容在上文已说明,还是比较简单。下面几节会对相关原理做一个说明,让读者学习其原理,并且可以在自己的程序中使用。真正负责 Ribbon 负载均衡的是 Spring Cloud 定义的接口 LoadBalancerClient,下面看看这个接口的代码,代码如下所示。
package org.springframework.cloud.client.loadbalancer;
public interface LoadBalancerClient extends ServiceInstanceChooser {
<T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;
<T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException;
URI reconstructURI(ServiceInstance instance, URI original);
}
在上面的接口代码中定义了一些抽象方法。
-
execute:使用从负载均衡器中挑选出来的实例执行请求内容。
-
reconstructURI:为系统构建一个合适 URI,构建的 URI 形式是 “host: port”。在代码中,我们发现这里有一个 ServiceInstance 对象,在这个对象中就有 host 和 port 信息。
对于接口 LoadBalancerClient,在 Ribbon 中使用默认的实现类。当然,在 Spring Cloud 中 LoadBalancerClient 只有一个实现类,就是 RibbonLoadBalancerClient。下面,我们针对第一个 execute 方法进行说明。
首先,进入 RibbonLoadBalancerClient 看看 execute 的实现,代码如下所示。
public <T> T execute(String serviceId, LoadBalancerRequest<T>request, Object hint) throws IOException {
ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
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);
}
在上面的代码中,函数 getServer 获取具体的服务实例。在这里,我们获取到了服务实例,具体如何实现,看如下代码。
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");
}
在上面的代码中,我们发现服务的获取使用了 ILoadBalancer 接口的方法。我们主要看这个接口的功能,代码如下所示。
package com.netflix.loadbalancer;
public interface ILoadBalancer {
public void addServers(List<Server> newServers);
public Server chooseServer(Object key);
public void markServerDown(Server server);
@Deprecated
public List<Server> getServerList(boolean availableOnly);
public List<Server> getReachableServers();
public List<Server> getAllServers();
}
这个接口主要用于对负载均衡器做一些抽象,这里对接口的方法稍微做一些说明,下一章节再说明负载均衡器。
-
addServers:向负载均衡器的实例列表添加服务实例。
-
chooseServer:从负载均衡器的实例列表中选择一个具体的服务实例。
-
markServerDown:在负载均衡器中标注某个服务实例已经下线。
-
getReachableServers:获取正常使用的服务实例列表。
-
getAllServers:获取全部的服务实例列表,包括停止的服务实例,这里读者需要和 getReachableServers 做一个区别。