当前位置:网站首页>Ribbon源码分析之@LoadBalanced与LoadBalancerClient

Ribbon源码分析之@LoadBalanced与LoadBalancerClient

2022-06-24 18:58:00 华为云

Ribbon源码分析之@LoadBalanced与LoadBalancerClient

@LoadBalanced注解

@LoadBalanced注解用来给RestTemplate做标记,方便使用负载均衡的客户端LoadBalancerClient来配置它。

LoadBalancerClient:

public interface LoadBalancerClient {   /** * Choose a ServiceInstance from the LoadBalancer for the specified service * @param serviceId the service id to look up the LoadBalancer * @return a ServiceInstance that matches the serviceId */   ServiceInstance choose(String serviceId);   /** * execute request using a ServiceInstance from the LoadBalancer for the specified * service * @param serviceId the service id to look up the LoadBalancer * @param request allows implementations to execute pre and post actions such as * incrementing metrics * @return the result of the LoadBalancerRequest callback on the selected * ServiceInstance */   <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;   /** * Create a proper URI with a real host and port for systems to utilize. * Some systems use a URI with the logical serivce name as the host, * such as http://myservice/path/to/service. This will replace the * service name with the host:port from the ServiceInstance. * @param instance * @param original a URI with the host as a logical service name * @return a reconstructed URI */   URI reconstructURI(ServiceInstance instance, URI original);}

接口中,我们通过定义抽象方法来了解客户端负载均衡器中应具备的能力

  • ServiceInstance choose(String serviceId); 根据传入的服务名serviceId从负载均衡器中挑选一个对应服务的实例

  • T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException; 从负载均衡器中挑选出的服务实例来执行请求内容

  • URI reconstructURI(ServiceInstance instance, URI original); 为系统构建一个合适的host:port 形式的URI

    在分布式系统中,我们使用逻辑上的服务名称作为host来构建URI进行请求。在操作定义中,ServiceInstance对象带有host和port具体服务实例,后者URI对象使用逻辑服务名定义为host的URI,返回的URI内容是通过ServiceInstance 的服务实例详情拼接出来的host:port形式的请求地址。

小知识,大挑战!本文正在参与「程序员必备小知识」创作活动

LoadBalancerClient

LoadBalancerAutoConfiguration实现客户端负载均衡器的自动化配置类。

LoadBalancerAutoConfiguration:

import java.util.ArrayList;import java.util.Collections;import java.util.List;import org.springframework.beans.factory.SmartInitializingSingleton;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.http.client.ClientHttpRequestInterceptor;import org.springframework.web.client.RestTemplate;/** * Auto configuration for Ribbon (client side load balancing). * * @author Spencer Gibb * @author Dave Syer */@Configuration@ConditionalOnClass(RestTemplate.class)@ConditionalOnBean(LoadBalancerClient.class)public class LoadBalancerAutoConfiguration {	@LoadBalanced	@Autowired(required = false)	private List<RestTemplate> restTemplates = Collections.emptyList();	@Bean	public SmartInitializingSingleton loadBalancedRestTemplateInitializer(			final List<RestTemplateCustomizer> customizers) {		return new SmartInitializingSingleton() {			@Override			public void afterSingletonsInstantiated() {				for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {					for (RestTemplateCustomizer customizer : customizers) {						customizer.customize(restTemplate);					}				}			}		};	}	@Bean	@ConditionalOnMissingBean	public RestTemplateCustomizer restTemplateCustomizer(			final LoadBalancerInterceptor loadBalancerInterceptor) {		return new RestTemplateCustomizer() {			@Override			public void customize(RestTemplate restTemplate) {				List<ClientHttpRequestInterceptor> list = new ArrayList<>(						restTemplate.getInterceptors());				list.add(loadBalancerInterceptor);				restTemplate.setInterceptors(list);			}		};	}	@Bean	public LoadBalancerInterceptor ribbonInterceptor(			LoadBalancerClient loadBalancerClient) {		return new LoadBalancerInterceptor(loadBalancerClient);	}}

LoadBalancerAutoConfiguration类头的注解表示Ribbon实现的负载均衡自动化配置需要满足两个条件

  • @ConditionalOnClass(RestTemplate.class):RestTemplate必须在当前工程的环境中
  • @ConditionalOnBean(LoadBalancerClient.class):在Spring的Bean工厂中必须有LoadBalancerClient的实现Bean

自动化配置类中主要做三件事:

  • 创建一个LoadBalancerInterceptor的Bean,用于实现对客户端发起请求时进行拦截,实现客户端负载均衡
  • 创建RestTemplateCustomizer的Bean,用于RestTemplate增加LoadBalancerInterceptor拦截器
  • 维护被LoadBalanced注解修饰的RestTemplate对象列表,并在这里进行初始化,通过RestTemplateCustomizer的实例给客户端负载均衡的RestTemplate增加LoadBalancerInterceptor拦截器

总结

这就是LoadBalancerAutoConfiguration的源码分析,它可以实现客户端负载均衡器的自动化配置类。这下一篇文章中我们要分析拦截器LoadBalancerInterceptor做了什么功能,我们下一篇文章不见不散咯。让我们一起深入Ribbon源码,共同学习

原网站

版权声明
本文为[华为云]所创,转载请带上原文链接,感谢
https://bbs.huaweicloud.com/blogs/361223