LoadBalancerInterceptor
该类唯一被使用的地方就是LoadBalancerAutoConfiguration里配置上去~
public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor { // 这个命名都不叫Client了,而叫loadBalancer~~~ private LoadBalancerClient loadBalancer; // 用于构建出一个Request private LoadBalancerRequestFactory requestFactory; ... // 省略构造函数(给这两个属性赋值) @Override public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException { final URI originalUri = request.getURI(); String serviceName = originalUri.getHost(); Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri); return this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution)); } }
此拦截器拦截请求后把它的serviceName委托给了LoadBalancerClient去执行,根据ServiceName可能对应N多个实际的Server,因此就可以从众多的Server中运用均衡算法,挑选出一个最为合适的Server做最终的请求(它持有真正的请求执行器ClientHttpRequestExecution)。
LoadBalancerClient
请求被拦截后,最终都是委托给了LoadBalancerClient处理。
// 由使用负载平衡器选择要向其发送请求的服务器的类实现 public interface ServiceInstanceChooser { // 从负载平衡器中为指定的服务选择Service服务实例。 // 也就是根据调用者传入的serviceId,负载均衡的选择出一个具体的实例出来 ServiceInstance choose(String serviceId); } // 它自己定义了三个方法 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; // 重新构造url:把url中原来写的服务名 换掉 换成实际的 URI reconstructURI(ServiceInstance instance, URI original); }
它只有一个实现类RibbonLoadBalancerClient(ServiceInstanceChooser是有多个实现类的~)。
RibbonLoadBalancerClient
首先我们应当关注它的choose()方法:
public class RibbonLoadBalancerClient implements LoadBalancerClient { @Override public ServiceInstance choose(String serviceId) { return choose(serviceId, null); } // hint:你可以理解成分组。若指定了,只会在这个偏好的分组里面去均衡选择 // 得到一个Server后,使用RibbonServer把server适配起来~~~ // 这样一个实例就选好了~~~真正请求会落在这个实例上~ public ServiceInstance choose(String serviceId, Object hint) { Server server = getServer(getLoadBalancer(serviceId), hint); if (server == null) { return null; } return new RibbonServer(serviceId, server, isSecure(server, serviceId), serverIntrospector(serviceId).getMetadata(server)); } // 根据ServiceId去找到一个属于它的负载均衡器 protected ILoadBalancer getLoadBalancer(String serviceId) { return this.clientFactory.getLoadBalancer(serviceId); } }
choose方法:传入serviceId,然后通过SpringClientFactory获取负载均衡器com.netflix.loadbalancer.ILoadBalancer,最终委托给它的chooseServer()方法选取到一个com.netflix.loadbalancer.Server实例,也就是说真正完成Server选取的是ILoadBalancer。
ILoadBalancer以及它相关的类是一个较为庞大的体系,本文不做更多的展开,而是只聚焦在我们的流程上
LoadBalancerInterceptor执行的时候是直接委托执行的loadBalancer.execute()这个方法:
RibbonLoadBalancerClient: // hint此处传值为null:一视同仁 // 说明:LoadBalancerRequest是通过LoadBalancerRequestFactory.createRequest(request, body, execution)创建出来的 // 它实现LoadBalancerRequest接口是用的一个匿名内部类,泛型类型是ClientHttpResponse // 因为最终执行的显然还是执行器:ClientHttpRequestExecution.execute() @Override public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException { return execute(serviceId, request, null); } // public方法(非接口方法) public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) throws IOException { // 同上:拿到负载均衡器,然后拿到一个serverInstance实例 ILoadBalancer loadBalancer = getLoadBalancer(serviceId); Server server = getServer(loadBalancer, hint); if (server == null) { // 若没找到就直接抛出异常。这里使用的是IllegalStateException这个异常 throw new IllegalStateException("No instances available for " + serviceId); } // 把Server适配为RibbonServer isSecure:客户端是否安全 // serverIntrospector内省 参考配置文件:ServerIntrospectorProperties RibbonServer ribbonServer = new RibbonServer(serviceId, server, isSecure(server, serviceId), serverIntrospector(serviceId).getMetadata(server)); //调用本类的重载接口方法~~~~~ return execute(serviceId, ribbonServer, request); } // 接口方法:它的参数是ServiceInstance --> 已经确定了唯一的Server实例~~~ @Override public <T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException { // 拿到Server)(说白了,RibbonServer是execute时的唯一实现) Server server = null; if (serviceInstance instanceof RibbonServer) { server = ((RibbonServer) serviceInstance).getServer(); } if (server == null) { throw new IllegalStateException("No instances available for " + serviceId); } // 说明:执行的上下文是和serviceId绑定的 RibbonLoadBalancerContext context = this.clientFactory.getLoadBalancerContext(serviceId); ... // 真正的向server发送请求,得到返回值 // 因为有拦截器,所以这里肯定说执行的是InterceptingRequestExecution.execute()方法 // so会调用ServiceRequestWrapper.getURI(),从而就会调用reconstructURI()方法 T returnVal = request.apply(serviceInstance); return returnVal; ... // 异常处理 }
returnVal是一个ClientHttpResponse,最后交给handleResponse()方法来处理异常情况(若存在的话),若无异常就交给提取器提值:responseExtractor.extractData(response),这样整个请求就算全部完成了。