@LoadBalanced注解的实现原理
- @LoadBalanced
@LoadBalanced注解通常结合RestTemplate使用,RestTemplate是SpringCloud提供的一个编程式的实现远程过程调用的组件,简单来说就是可以实现发送http请求。但是在基于服务发现发送请求时,RestTemplate自己无法实现负载均衡,通常要标注@LoadBalanced。
虽然之后一个RestTemplate对象,但这个对象是线程安全的,多个线程在共同使用这个对象时不会有线程安全问题。
@LoadBalanced
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
- 注解实现原理
@LoadBalanced注解是spring-cloud-starter-loadbalancer依赖引入的,这个依赖引入了LoadBalancerAutoConfiguration。
简单看一下这个类的源码:
@Configuration(
proxyBeanMethods = false
)
@Conditional({BlockingRestClassesPresentCondition.class})
@ConditionalOnBean({LoadBalancerClient.class})
@EnableConfigurationProperties({LoadBalancerClientsProperties.class})
public class LoadBalancerAutoConfiguration {
@LoadBalanced
@Autowired(
required = false
)
private List<RestTemplate> restTemplates = Collections.emptyList();
@Autowired(
required = false
)
private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList();
public LoadBalancerAutoConfiguration() {
}
@Bean
public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {
return () -> restTemplateCustomizers.ifAvailable((customizers) -> {
for(RestTemplate restTemplate : 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 {
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);
};
}
@Bean
@ConditionalOnBean({LoadBalancerInterceptor.class})
@ConditionalOnMissingBean
LoadBalancerRestClientBuilderBeanPostProcessor lbRestClientPostProcessor(final LoadBalancerInterceptor loadBalancerInterceptor, ApplicationContext context) {
return new LoadBalancerRestClientBuilderBeanPostProcessor(loadBalancerInterceptor, context);
}
}
private static class RetryMissingOrDisabledCondition extends AnyNestedCondition {
RetryMissingOrDisabledCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@ConditionalOnMissingClass({"org.springframework.retry.support.RetryTemplate"})
static class RetryTemplateMissing {
RetryTemplateMissing() {
}
}
@ConditionalOnProperty(
value = {"spring.cloud.loadbalancer.retry.enabled"},
havingValue = "false"
)
static class RetryDisabled {
RetryDisabled() {
}
}
}
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({RetryTemplate.class})
public static class RetryAutoConfiguration {
public RetryAutoConfiguration() {
}
@Bean
@ConditionalOnMissingBean
public LoadBalancedRetryFactory loadBalancedRetryFactory() {
return new LoadBalancedRetryFactory() {
};
}
}
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({RetryTemplate.class})
@ConditionalOnBean({ReactiveLoadBalancer.Factory.class})
@ConditionalOnProperty(
value = {"spring.cloud.loadbalancer.retry.enabled"},
matchIfMissing = true
)
public static class RetryInterceptorAutoConfiguration {
public RetryInterceptorAutoConfiguration() {
}
@Bean
@ConditionalOnMissingBean
public RetryLoadBalancerInterceptor loadBalancerInterceptor(LoadBalancerClient loadBalancerClient, LoadBalancerRequestFactory requestFactory, LoadBalancedRetryFactory loadBalancedRetryFactory, ReactiveLoadBalancer.Factory<ServiceInstance> loadBalancerFactory) {
return new RetryLoadBalancerInterceptor(loadBalancerClient, requestFactory, loadBalancedRetryFactory, loadBalancerFactory);
}
@Bean
@ConditionalOnMissingBean
public RestTemplateCustomizer restTemplateCustomizer(final RetryLoadBalancerInterceptor loadBalancerInterceptor) {
return (restTemplate) -> {
List<ClientHttpRequestInterceptor> list = new ArrayList(restTemplate.getInterceptors());
list.add(loadBalancerInterceptor);
restTemplate.setInterceptors(list);
};
}
@Bean
@ConditionalOnBean({RetryLoadBalancerInterceptor.class})
@ConditionalOnMissingBean
LoadBalancerRestClientBuilderBeanPostProcessor lbRestClientPostProcessor(final RetryLoadBalancerInterceptor loadBalancerInterceptor, ApplicationContext context) {
return new LoadBalancerRestClientBuilderBeanPostProcessor(loadBalancerInterceptor, context);
}
}
}
核心实现原理:
- 从容器中拿到所有标注了@LoadBalanced注解的Bean,所以没有标注 @LoadBalanced注解的RestTemplate是无法实现负载均衡的。
@LoadBalanced
@Autowired(
required = false
)
private List<RestTemplate> restTemplates = Collections.emptyList();
- 拿到这些Bean对象之后,给这些Bean对象设置请求拦截器
@Bean
public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {
return () -> restTemplateCustomizers.ifAvailable((customizers) -> {
for(RestTemplate restTemplate : this.restTemplates) {
for(RestTemplateCustomizer customizer : customizers) {
customizer.customize(restTemplate);
}
}
});
}
这里就是调用了customizer.customize(restTemplate) 来为每一个RestTemplate添加拦截器。
RestTemplateCustomizer 是一个函数式接口,同样在LoadBalancerAutoConfiguration进行了实现
public interface RestTemplateCustomizer {
void customize(RestTemplate restTemplate);
}
@Bean
@ConditionalOnMissingBean
public RestTemplateCustomizer restTemplateCustomizer(final LoadBalancerInterceptor loadBalancerInterceptor) {
return (restTemplate) -> {
List<ClientHttpRequestInterceptor> list = new ArrayList(restTemplate.getInterceptors());
list.add(loadBalancerInterceptor);
restTemplate.setInterceptors(list);
};
}
很明显这里就是使用lambda表达式定义了一个RestTemplateCustomizer 的实现。而这个方法就是容器中获取LoadBalancerInterceptor,然后获取restTemplate已有的拦截器,并且加入新的拦截器再重新赋值。
- LoadBalancerInterceptor
看一下LoadBalancerInterceptor的实现,这个是实现负载均衡的关键
public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {
private LoadBalancerClient loadBalancer;
private LoadBalancerRequestFactory requestFactory;
public LoadBalancerInterceptor(LoadBalancerClient loadBalancer, LoadBalancerRequestFactory requestFactory) {
this.loadBalancer = loadBalancer;
this.requestFactory = requestFactory;
}
public LoadBalancerInterceptor(LoadBalancerClient loadBalancer) {
this(loadBalancer, new LoadBalancerRequestFactory(loadBalancer));
}
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException {
URI originalUri = request.getURI();
String serviceName = originalUri.getHost();
Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);
return (ClientHttpResponse)this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution));
}
}
很明显可以看到intercept中使用了LoadBalancerClient进行了服务负载均衡。
简而言之就是LoadBalancerAutoConfiguration这个类获取到了容器中所有的RestTemplate组件,并添加了负载均衡拦截器,这样@Bean的RestTemplate自动就有了负载均衡能力。
原文地址:https://blog.csdn.net/qq_43750656/article/details/145247516
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!