cloud 客户端负载- @LoadBalanced 工作原理

本文深入探讨了Spring中如何通过@LoadBalanced注解实现客户端负载均衡。详细分析了该注解的工作原理及其与@Qualifier的关系,并介绍了配置类LoadBalancerAutoConfiguration的作用。
摘要由CSDN通过智能技术生成

cloud 客户端负载- @LoadBalanced 工作原理

问题

在 spring 中,为什么通过加入 @LoadBalanced 注解就可以实现客户端负载

@LoadBalanced 定义

@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Qualifier                 //不同
public @interface LoadBalanced {

}

认真观查发现,这个注解比普通定义的注解的多了一个 @Qualifier 注解

LoadBalancerAutoConfiguration配置:

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RestTemplate.class)
@ConditionalOnBean(LoadBalancerClient.class)
@EnableConfigurationProperties(LoadBalancerProperties.class)
public class LoadBalancerAutoConfiguration {

    //注入 加了@LoadBalanced注解的 RestTemplate
	@LoadBalanced
	@Autowired(required = false)
	private List<RestTemplate> restTemplates = Collections.emptyList();

	@Autowired(required = false)
	private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList();

	@Bean
	public SmartInitializingSingleton 
			loadBalancedRestTemplateInitializerDeprecated(
			final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {
		return () -> restTemplateCustomizers.ifAvailable(customizers -> {
			for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {
				for (RestTemplateCustomizer customizer : customizers) {
					customizer.customize(restTemplate);
				}
			}
		});
	}

	@Bean
	@ConditionalOnMissingBean
	public LoadBalancerRequestFactory 
			loadBalancerRequestFactory(LoadBalancerClient loadBalancerClient) {
		return new LoadBalancerRequestFactory(loadBalancerClient, this.transformers);
	}

	@Configuration(proxyBeanMethods = false)
	@Conditional(RetryMissingOrDisabledCondition.class)
	static class LoadBalancerInterceptorConfig {

		@Bean
		public LoadBalancerInterceptor 
					loadBalancerInterceptor(LoadBalancerClient loadBalancerClient,
				LoadBalancerRequestFactory requestFactory) {
			return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
		}

		@Bean
		@ConditionalOnMissingBean
		public RestTemplateCustomizer 
				restTemplateCustomizer(final LoadBalancerInterceptor loadBalancerInterceptor) {
			return restTemplate -> {
				List<ClientHttpRequestInterceptor> list 
							= new ArrayList<>(restTemplate.getInterceptors());
				list.add(loadBalancerInterceptor);
				restTemplate.setInterceptors(list);
			};
		}

	}

    //omit...

}

@LoadBalanced 工作原理

这里以 RestTemalate 为例

工作流程:

  • LoadBalancerRequestFactory 创建客户端负载 LoadBalancer

  • 创建 LoadBalancerInterceptor , 用来进行客户端负载拦截

  • RestTemplateCustomizer 用来定制RestTemplate, 这里是为 RestTempate 加入 LoadBalancerInterceptor 拦截

  • SmartInitializingSingleton: 容器中注入的RestTempate ,使用 RestTemplateCustomizer 进行定制化处理,这里是为每个RestTemplate 加入 LoadBalancerInterceptor 拦截

流程都有了,那这里有一个问题 使用@LoadBalanced 注解后, 是如何,或者是什么时候被加载到容器中的?

在回答这个问题之前,我们先看看 @Qualifier 作用

@Qualifier 作用

一般的使用方式

  1. 定义一个Bean ,并指定名称为 aaa
  2. 使用时,通过@Qualifier 指定Bean 的名称,注入aaa
//定义
@Bean("aaa")
public RestTemplate restTemplate(){
    return new RestTemplate();
}


//调用方
@Autowired
@Qualifier("aaa")
private RestTemplate restTemplate;

当容器中有两个或者多个相同类型Bean的时候,如果想要依赖注入其中的一个,可以有两种做法

  • 使用 @Resource 注解, 指定Bean的名称
  • 使用 @Auwired 和 @Qualifer 搭配使用, @Autowired 默认是依赖注入的方式是 ByType , 当容器中有多个Bean 时, 如果仅仅使用 @Autowired 时会报错,@Autowired 不能区别到底使用哪一个Bean, 所以需要通过 @Qualifier 指定一个具体的Bean
  • 当然也可以在定义Bean 的时候也使用上 , 如下
//定义
@Bean("aaa")
@Qualifier
public RestTemplate restTemplate(){
    return new RestTemplate();
}

@Bean("bbb")
public RestTemplate restTemplate(){
    return new RestTemplate();
}


//调用方
@RestController
public class IndexController {

    @Autowired
    @Qualifier
    private List<RestTemplate> list = Collections.emptyList();


    @Autowired
    @Qualifier
    private Map<String, RestTemplate> map = Collections.emptyMap();

    @GetMapping("/index")
    public String index(){
        System.out.println(list.size());
        System.out.println(map.size());
        return "ok";
    }

}


在这里插入图片描述

这里 的 list 大小就是 1, 即 @Autowired 只注入了@Qualifier 注解的Bean

看到这里, 我们的 @LoadBalanced 就有那么一点异曲同工之处了,只不过 @Qualifier 依附在 @LoadBalanced 注解之上了, 这也可以解释


public class LoadBalancerAutoConfiguration {

    //就可以解释这里为什么要加 @LoadBalanced 注解了
	@LoadBalanced
	@Autowired(required = false)
	private List<RestTemplate> restTemplates = Collections.emptyList();

}

回到我们的问题,自然迎刃而解了

good luck !

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值