最新实战案例锦集:《Spring Boot3实战案例合集》持续更新,每天至少更新一篇文章,订阅后将赠送文章最后展示的所有MD文档(学习笔记)。
环境:SpringBoot3.2.5
1. 简介
在上一篇文章中,我们详细的介绍了《服务注册与发现》底层工作原理,在阅读本篇文章前,请先查看如下文章:
推荐学习!拆解Spring Cloud 4大核心组件,彻底搞懂工作原理(服务注册与发现)
Spring Cloud LoadBalancer 是一个客户端负载均衡器,用于在微服务架构中实现服务间的负载均衡。Spring Cloud内部提供两种简单而有效的方式来选择目标服务实例。LoadBalancer 自动与服务发现机制(如Eureka、Consul或Nacos)集成,可以根据配置的策略(如轮询、随机选择)动态选择服务实例。
使用Spring Cloud LoadBalancer时,开发人员通常不需要在代码中直接使用其API。相反,Spring Cloud通过自动配置和注解(如@LoadBalanced)简化了集成过程。只需在RestTemplate、WebClient或RestClient上添加@LoadBalanced注解,即可启用负载均衡功能。这样,每次调用远程服务时,LoadBalancer会自动选择一个合适的服务实例。
接下来,我们将详细的介绍关于LoadBalancer组件的使用及底层工作原理。
2. 实战案例
2.1 基本使用及原理
在项目开发中,应用最多的负载均衡功能是使用 @LoadBalanced 注解,如下示例:
RestTemplate resetTemplate() {
return new RestTemplate() ;
}
WebClient.Builder webClientBuilder() {
return WebClient.builder() ;
}
RestClient.Builder restClient() {
return RestClient.builder() ;
}
我们在使用的时候就可以直接通过目标的服务名来调用接口:
public Object rtget() {
return this.restTemplate.getForObject("http://pack/index", String.class) ;
}
public Object rcget() {
return this.restClientBuilder.build()
.get()
.uri("http://pack/index")
.retrieve()
.body(String.class) ;
}
public Mono<String> wcget() {
return this.webClientBuilder.build()
.get().uri("http://pack/index")
.retrieve()
.bodyToMono(String.class) ;
}
通过上面的三种客户端都实现了负载均衡的能力,而我们仅仅是使用了@LoadBalanced 注解。接下来,我们将介绍他们的实现原理。
实现原理
RestTemplate 与 RestClient
他们两个的实现原理是一样的,都是通过一个拦截器来处理请求的URI。在下面的自动配置类中:
public class LoadBalancerAutoConfiguration {
// 获取当前容器中定义的所有RestTemplate类型的Bean对象
// 并且限定了这些定义的RestTemplate必须使用@LoadBalanced注解
false) (required =
private List<RestTemplate> restTemplates = Collections.emptyList();
public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(
ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers)
// 获取容器中自定义的RestTemplateCustomizer,该类就是用来自定义RestTemplate
return () -> restTemplateCustomizers.ifAvailable(customizers -> {
for (RestTemplate restTemplate : restTemplates) {
for (RestTemplateCustomizer customizer : customizers) {
customizer.customize(restTemplate);
}
}
});
}
// 该拦截器是关键,它就是用来根据你当前请求的服务名查找正确的服务地址
public LoadBalancerInterceptor loadBalancerInterceptor(...)
return new LoadBalancerInterceptor(...);
}
// 默认该自动配置类中定义了一个RestTemplateCustomizer
public RestTemplateCustomizer restTemplateCustomizer(
LoadBalancerInterceptor loadBalancerInterceptor) {
return restTemplate -> {
// 为我们的RestTemplate添加拦截器(上面的LoadBalancerInterceptor )
List<ClientHttpRequestInterceptor> list = new ArrayList<>(restTemplate.getInterceptors());
list.add(loadBalancerInterceptor) ;
restTemplate.setInterceptors(list) ;
};
}
}
下面是LoadBalancerInterceptor拦截器的执行原理