微服务架构之均衡组件 Ribbon解析:LoadBalancerClient
Ribbon
是一个可以管理Http和TCP客户端的客户端负载均衡器。Feign
已经在使用Ribbon
了,如果你使用过@FeignClient
,那么Ribbon
也会被使用。
Ribbon
的核心思想就是named client,也就是带有名称的Ribbon Client。每个Client由可配置的组件构成,负责一类服务的调用请求。Spring Cloud
通过RibbonClientConfiguration
为每个named client创建一个ApplicationContext
来进行组件装配。这些组件就包括ILoadBalancer
,RestClient
和ServerListFilter
等。
LoadBalancerClient 实现解析
Ribbon
与RestTemplate
和Feign
之间的工作原理是阅读本文的基础。接下来,本文将会对LoadBalancerClient
进行负载均衡的具体原理和实现。
LoadBalancerClient
是Ribbon
项目的核心类之一,可以在RestTemplate
发送网络请求时替代RestTemplate
进行网络调用。
/**
* 客户端负载均衡器的接口
*/
public interface LoadBalancerClient extends ServiceInstanceChooser {
/**
* 从serviceId所代表的服务列表中选择一个服务器来发送网络请求
*/
<T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;
/**
* 同上。
*/
<T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException;
/**
* 构建网络请求URI
*/
URI reconstructURI(ServiceInstance instance, URI original);
}
LoadBalancerClient
接口继承了ServiceInstanceChooser
来
从服务器列表中依据负载均衡策略选出一个服务器。
//实现该类来选择一个服务器来发送请求。
public interface ServiceInstanceChooser {
/**
* 根据serviceId从服务器列表中选择一个ServiceInstance
**/
ServiceInstance choose(String serviceId);
}
RibbonLoadBalancerClient
是LoadBalancerClient
的实现类之一,它的execute
会首先使用ILoadBalancer
来选择Server
,然后将Server
封装成RibbonServer
对象,最后再调用LoadBalancerRequest
的apply
函数进行网络请求的处理。
@Override
public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {
//每次发送请求都会创建一个ILoadBalancer,会涉及到选举规则(IRule),服务器列表集群(ServerList)和检验服务是否存在(IPing)等细节实现
ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
//选举一个具体的server,会涉及到选举规则,服务器列表和服务器是否存在等问题。
Server server = getServer(loadBalancer);
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);
}
ILoadBalancer
的初始化过程,getLoadBalancer
函数直接调用了SpringClientFactory
的getLoadBalancer
函数。SpringClientFactory
是NamedContextFactory
的实现类,关于NamedContextFactory
的机制我们在Feign
章节中已经详细讲解过了,通过它可以实现多套Bean实例的管理。
public ILoadBalancer getLoadBalancer(String name) {
return getInstance(name, ILoadBalancer.class);
}
getServer
则是直接调用了ILoadBalancer
的chooseServer
函数来使用负载均衡策略从已知的服务器列表中选出一个服务器。
protected Server getServer(ILoadBalancer loadBalancer) {
if (loadBalancer == null) {
return null;
}
return loadBalancer.chooseServer("default");
}
execute
函数中使用LoadBalancerRequest
实例的apply
函数,将之前根据负载均衡策略选择出来的服务器作为参数传递进去,进行真正的HTTP请求的发送。
public <T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException {
Server server = null;
if(serviceInstance instanceof RibbonServer) {
server = ((RibbonServer)serviceInstance).getServer();
}
RibbonLoadBalancerContext context = this.clientFactory
.getLoadBalancerContext(serviceId);
RibbonStatsRecorder statsRecorder = new RibbonStatsRecorder(context, server);
try {
T returnVal = request.apply(serviceInstance);
statsRecorder.recordStats(returnVal);
return returnVal;
}
catch (IOException ex) {
statsRecorder.recordStats(ex);
throw ex;
}
catch (Exception ex) {
statsRecorder.recordStats(ex);
ReflectionUtils.rethrowRuntimeException(ex);
}
return null;
}
LoadBalancerRequest
的apply
函数的具体实现本书不再详细讲解,因为Ribbon
最为重要的部分就是使用负载均衡策略来选择服务器,也就是ILoadBalancer
的chooseServer
函数的实现,本书会在接下来的小节里对其进行详细的讲解。
小结
当系统面临大量的用户访问,负载过高的时候,通常会使用增加服务器数量来进行横向扩展,多个服务器的负载需要均衡,以免有的服务器负载较大,而有的服务器负载较小。通过负载均衡,使得集群中的服务器的负载保持在稳定高效的状态,从而提高整个系统的处理能力。
- 点赞
- 收藏
- 关注作者
评论(0)