Spring Cloud LoadBalancer自动配置源码分析
下面笔者结合源码来分析负载均衡器的原理,主要解释它到底是怎样起作用的,以及它都做了什么。
在编码时仅仅添加了 spring-cloud-starter-loadbalancer
依赖和一个 @LoadBalance
注解,负载均衡器就生效了。毋庸置疑,肯定是 Spring Boot
框架的自动装配(Auto Configuration
)机制生效了。
本节介绍的 LoadBalancer
自动配置类是 org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration
,其源码在 spring-cloud-commons-3.1.1.jar
中,如图 7-6 所示。
有一个与 LoadBalancerAutoConfiguration
同名的类,不过类路径不同,读者要注意区分。

LoadBalancerAutoConfiguration
自动配置类的定义和源码注释如下:
package org.springframework.cloud.client.loadbalancer;
// 配置类
@Configuration(proxyBeanMethods = false)
// 当前项目的 classpath 下存在 RestTemplate 类时生效
@ConditionalOnClass(RestTemplate.class)
// 当前 IoC 容器中存在 LoadBalancerClient 类型的 Bean 时生效
@ConditionalOnBean(LoadBalancerClient.class)
@EnableConfigurationProperties(LoadBalancerClientsProperties.class)
public class LoadBalancerAutoConfiguration {
省略部分代码
@Bean // 注册 LoadBalancerRequestFactory 到 IoC 容器中
@ConditionalOnMissingBean // 当前 IoC 容器中不存在 LoadBalancerRequestFactory类型的 Bean 时注册
public LoadBalancerRequestFactory loadBalancerRequestFactory(
LoadBalancerClient loadBalancerClient) {
return new LoadBalancerRequestFactory(loadBalancerClient,
this.transformers);
}
@Configuration(proxyBeanMethods = false)
@Conditional(RetryMissingOrDisabledCondition.class)
static class LoadBalancerInterceptorConfig {
@Bean // 注册 LoadBalancerInterceptor 到 IoC 容器中
public LoadBalancerInterceptor loadBalancerInterceptor(
LoadBalancerClient loadBalancerClient,
LoadBalancerRequestFactory requestFactory) {
return new LoadBalancerInterceptor(loadBalancerClient,
requestFactory);
}
}
@Bean // 注册 RestTemplateCustomizer 到 IoC 容器中
@ConditionalOnMissingBean // 当前 IoC 容器中不存在 RestTemplateCustomizer 类型的 Bean 时注册
public RestTemplateCustomizer restTemplateCustomizer(final
LoadBalancerInterceptor loadBalancerInterceptor) {
return restTemplate -> {
List<ClientHttpRequestInterceptor> list = new ArrayList<>();
list.addAll(restTemplate.getInterceptors());
list.add(loadBalancerInterceptor);
restTemplate.setInterceptors(list);
};
}
}
java
由源码可知,LoadBalancerAutoConfiguration
自动配置类的生效条件有两个。
一个条件是当前项目的 classpath
下存在 RestTemplate
类。由于在 pom.xml
文件中引入了 spring-boot-starter-web
依赖,而 spring-boot-starter-web
依赖中包括 spring-web.jar
,RestTemplate
类就在 spring-web.jar
中定义,因此该条件会生效。
另一个条件是当前 IoC
容器中存在 LoadBalancerClient
类型的 Bean
。LoadBalancerClient
是一个接口,其唯一的实现类为 org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient
类。而 BlockingLoadBalancerClient
类也有一个自动配置类 BlockingLoadBalancerClientAutoConfiguration
,在 BlockingLoadBalancerClientAutoConfiguration
类定义上有以下明确的代码:
@AutoConfigureBefore({ org.springframework.cloud.client.loadbalancer.
LoadBalancerAutoConfiguration.class,
AsyncLoadBalancerAutoConfiguration.class })
java
也就是说,自动配置类 BlockingLoadBalancerClientAutoConfiguration
一定会在自动配置类 org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration
之前先走完自动配置流程,然后向 IoC
容器中注册 BlockingLoadBalancerClient
类型的 Bean
。所以第二个条件也会生效。
继续来看 LoadBalancerAutoConfiguration
自动配置类生效后做了哪些事情。
根据源码可知,在自动配置类生效后,会向 IoC
容器中注册一个 org.springframework.cloud.client.loadbalancer.LoadBalancerRequestFactory
类型的 Bean
、一个 org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor
类型的 Bean
和一个 RestTemplateCustomizer
类型的 Bean
。其中,RestTemplateCustomizer
是 RestTemplate
类的定制器,也就是说,在该自动配置类生效后,会获取当前 IoC
容器中 RestTemplate
类型的 Bean
,并且把一个 LoadBalancerInterceptor
类型的拦截器注入 RestTemplate
类型的 Bean
。
简单来说,就是 LoadBalancerAutoConfiguration
自动配置类生效后,会在 RestTemplate
工具中做定制化的修改,“塞” 一个拦截器进去。
为了更直观地感受这个过程,打断点后走一遍流程。在自定义的 RestTemplateConfig
类中的第 23 行、LoadBalancerAutoConfiguration
类中的第 89 行和第 98 行分别打一个断点,之后以 Debug
模式启动项目。
在启动过程中,程序直接在 RestTemplateConfig
类中的第 23 行这个断点处停住了,如图 7-7 所示。
此时正在构造一个 RestTemplate
类型的 Bean
并将其注册到 IoC
容器中。注意此时构造的这个 Bean——RestTemplate@4735(这是笔者在分析时的结果,读者在分析时生成的 RestTemplate
内容可能不同)。单击 “Resume Program” 按钮跳过这个断点,程序将分别在 LoadBalancerAutoConfiguration
类中的第 89 行和第 98 行的断点处停住。
如图 7-8 所示,第 98 行的这行代码在执行时会向 IoC
容器中 RestTemplate
类型的 Bean
添加一个拦截器,而此时获取的 RestTemplate
类型的 Bean
就是自定义 RestTemplateConfig
类中构造的那个 Bean——RestTemplate@4735。也就是说,本来 RestTemplate
类好好的,但是 LoadBalancer
集成进来之后,把它给改造了,往里面加了一个拦截器,拦截器中有一个重要的类 BlockingLoadBalancerClient
。


以上就是 LoadBalancer
自动配置时的源码分析,主要包括自动配置类的生效条件解释,以及自动配置类生效之后做了哪些事情,读者可以根据分析过程理解和实践。
需要注意,LoadBalancer
自动配置类不止本节中提到的 LoadBalancerAutoConfiguration
这一个。如果未使用 RestTemplate
工具,而使用了 Web Flux
的 WebClient
工具,那么它的自动配置类是另外一个。当前的自动配置类就不会生效了,因篇幅有限,不再拓展,感兴趣的读者可以自行查阅相关资料,其过程和作用是类似的。