继续学习负载均衡组件Ribbon。
组件分析
从springcloud开始分析。
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;
}
public interface ServiceInstanceChooser {
ServiceInstance choose(String serviceId);
}
负载均衡客户端LoadBalancerClient,可以执行负载均衡请求。
public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {
private LoadBalancerClient loadBalancer;
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException {
URI originalUri = request.getURI();
String serviceName = originalUri.getHost();
Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);
return (ClientHttpResponse)this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution));
}
}
负载均衡拦截器LoadBalancerInterceptor拦截HttpRequest交给LoadBalancerClient去执行。
其它的还有RestTemplateCustomizer来定制Restemplate,将LoadBalancerInterceptor添加到Restemplate中,让Restemplate发送请求时被拦截器拦截,进而让负载均衡客户端来执行请求,这个不是重点,因为springcloud大都可能采用feign来进行http请求调用。
大致流程如下:
总的来看springcloud负载均衡主要就是定义 LoadBalancerClient来处理LoadBalancerRequest,具体结构如下:
可以看到LoadBalancerClient应具选择服务实例、执行负载均衡请求的功能。那么现在来看看Ribbon是如何具体做的负载均衡,当然springcloud自己也做了一套负载均衡实现BlockingLoadBalancerClient,这里暂且先说下Ribbon的实现RibbonLoadBalancerClient。
public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) throws IOException {
ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId);
Server server = this.getServer(loadBalancer, hint);
if (server == null) {
throw new IllegalStateException("No instances available for " + serviceId);
} else {
RibbonLoadBalancerClient.RibbonServer ribbonServer = new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server));
return this.execute(serviceId, (ServiceInstance)ribbonServer, (LoadBalancerRequest)request);
}
}
可以看到RibbonLoadBalancerClient执行请求大致分3步,1、通过服务实例获取负载均衡器,2、让负载据衡器选出一个服务实例,3、向该服务实例发送请求。那么接下来看看如何获取ILoadBalancer。
最终发现是从spring容器中获取的,当然如果获取不到,会通过IClientConfig配置实例化。那么接下来看看负载据衡器如何选择服务实例。
DynamicServerListLoadBalancer维护了负载均衡器的本地服务列表,ServerListUpdater负责更新该列表。ServerList有获取服务列表的功能,这里留作扩展比如通过各种注册中心客户端获取服务列表。
总的来说负载均衡器获取服务实例的过程大致如下:
IRule通过对服务列表应用负载均衡算法得到Server,如RoundRobin轮询选择。
总结
今天先不说后续请求如何执行了,后续和feign一起学习。那总的看来Ribbon就是通过负载均衡器维护的服务列表,应用负载均衡算法实现负载均衡(服务实例选择)。