Ribbon源码系列——负载均衡类体系与拦截器
再看@LoadBalanced注解
上一篇文章中我们看到过@LoadBalanced注解的源码:

我们发现这个注解上面有一行注释,指引我们去看LoadBalancerClient类,我们就跟着这个线索去看一下
LoadBalancerClient负载均衡客户端


LoadBalancerClient接口,继承自ServiceInstanceChooser接口,ServiceInstanceChooser提供了一个方法,可以通过服务ID选择一个具体的服务实例。这,这不就是我们负载均衡的意义么,传入一个服务标识,组件帮我选择一个适当的服务实例!
再来看LoadBalancerClient接口本身提供的方法:
- execute:根据传入的服务ID和请求执行类,来执行一个具体的请求,返回请求结果
- reconstructURI:根据传入的服务实例和URI,返回一个具体host:port形式的URI
总结:LoadBalancerClient这个接口提供的功能与我们研究的负载均衡的功能高度契合,我们有理由相信,这个类就是Ribbon的核心类。
LoadBalancerAutoConfiguration自动装配
之前我们全局搜索@LoadBalanced注解的时候,注意到一个类注入了@LoadBalanced修饰的RestTemplate,他就是LoadBalancerAutoConfiguration类,我们知道在SpringBoot项目中,XXXAutoConfiguration一般都用来将某个组件的配置,自动装配进Spring容器,所以我们有理由相信这个类是Ribbon自动装配的配置类:

我们可以看到,LoadBalancerAutoConfiguration配置类帮我们注册了多个Bean,包括:
- LoadBalancerRequestFactory
- LoadBalancerInterceptor
- RestTemplateCustomizer
这个自动配置类中的Bean,大家刚接触的时候可能会直接懵掉,确实有点复杂。
Spring体系的源码都有这个特点,即:
- 类设计遵循单一职责原则
- 大量使用继承、多态
这样做的好处是单个类的职责非常清晰,看到接口或抽象类就基本可以理清功能。坏处是类体系复杂且庞大,对于初学者来说不太友好,遇到这种情况,笔者的经验是画类图,用自己的话来理解每个类的职责。下文会给出笔者画的图
整体类图梳理
笔者整理的LoadBalancerAutoConfiguration自动装配的类图如下:

从图中可以看出来,负载均衡拦截器最终由负载均衡客户端构造出来,理论上可以具备负载均衡客户端的功能,即选择服务实例和执行请求。Spring通过RestTemplateCustomizer定制器将拦截器定制到RestTemplate中,这样就能完成对RestTemplate的拦截了,我们合理猜想,负载均衡的功能就实现在拦截器中。
ClientHttpRequestInterceptor拦截器
SpringBoot提供了ClientHttpRequestInterceptor拦截器接口,实现这个拦截器接口的intercept方法可以对通过RestTemplate发起的请求和响应做一些拦截性的处理。通常请求是这样被处理的:
- 执行拦截器对request的拦截
- 执行http 请求或直接返回
- 执行拦截器对response的拦截
我们来看一下具体的实现类LoadBalancerInterceptor的源码:

在红杠的部分可以看到,拦截器最后正是调用了LoadBalancerClient#execute完全拦截了RestTemplate的原有请求。
本篇文章先到这里,总结一下:本文主要梳理了LoadBalancerAutoConfiguration注入到Spring容器中的类整体体系,最终发现是通过LoadBalancerInterceptor拦截器,调用了LoadBalancerClient#execute拦截了RestTemplate的原有请求逻辑,完成了负载均衡的功能。
Over🥽

浙公网安备 33010602011771号