推荐学习!拆解Spring Cloud 4大核心组件,彻底搞懂工作原理(负载均衡)

文摘   2024-11-19 19:00   新疆  

最新实战案例锦集:《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)简化了集成过程。只需在RestTemplateWebClientRestClient上添加@LoadBalanced注解,即可启用负载均衡功能。这样,每次调用远程服务时,LoadBalancer会自动选择一个合适的服务实例。

接下来,我们将详细的介绍关于LoadBalancer组件的使用及底层工作原理。

2. 实战案例

2.1 基本使用及原理

在项目开发中,应用最多的负载均衡功能是使用 @LoadBalanced 注解,如下示例:

@Bean@LoadBalancedRestTemplate resetTemplate() {  return new RestTemplate() ;}@Bean@LoadBalancedWebClient.Builder webClientBuilder() {  return WebClient.builder() ;}@Bean@LoadBalancedRestClient.Builder restClient() {  return RestClient.builder() ;}

我们在使用的时候就可以直接通过目标的服务名来调用接口:

@GetMapping("/rt/get")public Object rtget() {  return this.restTemplate.getForObject("http://pack/index", String.class) ;}
@GetMapping("/rc/get")public Object rcget() { return this.restClientBuilder.build() .get() .uri("http://pack/index") .retrieve() .body(String.class) ;}
@GetMapping("/wc/get")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注解  @LoadBalanced  @Autowired(required = false)  private List<RestTemplate> restTemplates = Collections.emptyList();    @Bean  public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(      ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers)    // 获取容器中自定义的RestTemplateCustomizer,该类就是用来自定义RestTemplate    return () -> restTemplateCustomizers.ifAvailable(customizers -> {      for (RestTemplate restTemplate : restTemplates) {        for (RestTemplateCustomizer customizer : customizers) {          customizer.customize(restTemplate);        }      }    });  }  // 该拦截器是关键,它就是用来根据你当前请求的服务名查找正确的服务地址  @Bean  public LoadBalancerInterceptor loadBalancerInterceptor(...)    return new LoadBalancerInterceptor(...);  }  // 默认该自动配置类中定义了一个RestTemplateCustomizer  @Bean  public RestTemplateCustomizer restTemplateCustomizer(    LoadBalancerInterceptor loadBalancerInterceptor) {    return restTemplate -> {      // 为我们的RestTemplate添加拦截器(上面的LoadBalancerInterceptor )      List<ClientHttpRequestInterceptor> list = new ArrayList<>(restTemplate.getInterceptors());      list.add(loadBalancerInterceptor) ;      restTemplate.setInterceptors(list) ;    };  }}

下面是LoadBalancerInterceptor拦截器的执行原理

Spring全家桶实战案例源码
spring, springboot, springcloud 案例开发详解
 最新文章