spring cloud ribbon 客户端负载均衡

ribbon 实现客户端的负载均衡

实现方式如下所示

只是在RestTemplate方法中加了一个注解@LoadBalanced

查看注解定义

该注解的作用是mark a RestTemplate bean to be configured to use a LoadBalancerClient

LoadBalanceClient 源码如下

对于LoadBalancerClient接口所在包 org.springframework.cloud.client.loadbalancer,

得到如下关系

LoadBalancerAutoConfiguration为实现客户端负载均衡的自动化配置类

在该自动化配置类中:

① 创建了一个LoadBalancerInterceptor的Bean,用于实现对客户端发起请求时进行拦截

,以实现客户端负载均衡

② 创建了一个RestTemplateCustomizer的Bean,用于给RestTemplate增加LoadBalancerInterceptor拦截器

③ 维护了一个被@LoadBalanced注解的RestTemplate对象列表

 

接下来,看一下LoadBalancerInterceptor拦截器

当一个被@LoadBalanced注解的RestTemplate对象对外发起HTTP请求时,会被LoadBalancerInterceptor类的intercept拦截。

LoadBalancerClient下的继承类RibbonLoadBalancerClient,调用execute方法

execute方法中 getServer获取具体的服务实例

可以看到这里获取具体服务实例的时候 使用了Netflix Ribbon自身的ILoadBalancer中的chooseServer方法

在ILoadBalancer接口中

对于该接口的实现,如下

那么在整合Ribbon的时候Spring Cloud默认采用了哪个具体实现呢?

在RibbonClientConfiguration配置类中,可以看到采用了ZoneAwareLoadBalancer

 

下面,再回到RibbonLoadBalancerClient的execute方法中,在通过ZoneAwareLoadBalancer的

chooseServer方法获取了负载均衡分配到的服务实例对象Server之后,将其内容包装成RibbonServer对象(该对象除了存储了服务实例的信息之外,还增加了服务名serviceId、是否HTTPS等其它信息),然后再回调LoadBalancerInterceptor请求拦截器中LoadBalancerRequest

的apply(final ServerInstance instance)方法,向一个实际的具体服务实例发起请求,

从而实现一开始以服务名为host的URI请求到host:post形式的实际访问地址的转换。

那么apply(final ServiceInstance instance)方法在接收到具体ServiceInstance实例后,

是如何通过LoadBalancerClient接口中的reconstructURI()操作来组成具体请求地址呢?

从apply的实现中,可以看到 先生成了ServiceRequestWrapper对象,该对象继承了

HttpRequestWrapper并重写了getURI()方法

 

在LoadBalancerInterceptor拦截器中,ClientHttpRequestExecution的实例具体执行

execution.execute(serviceRequest, body)时,会调用InterceptingClientHttpRequest下

InterceptingRequestExecution中execute方法

可以看到,在创建请求的时候requestFactory.createRequest(request.getURI(), request.getMethod()); 这里的request.getURI()会调用之前的ServiceRequestWrapper.getURI()

就会使用RibbonLoadBalancerClient.reconstructURI()来组织具体请求的服务实例地址

 

posted on 2018-07-20 16:26  持续在更新  阅读(178)  评论(0编辑  收藏  举报

导航