Spring Cloud 负载均衡解析

1、负载均衡的自动配置类

Spring Cloud 的负载均衡的自动注入类,注意这个类是spring-cloud-commons 模块下面的,org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration,而不是spring-cloud-loadbalancer模块下面的org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration,这两个同名

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RestTemplate.class)
@ConditionalOnBean(LoadBalancerClient.class)
@EnableConfigurationProperties(LoadBalancerRetryProperties.class)
public class LoadBalancerAutoConfiguration {
    @LoadBalanced
	@Autowired(required = false)
	private List<RestTemplate> restTemplates = Collections.emptyList();

这个自动注入依赖 RestTemplate 和 LoadBalancerClient,毕竟负载均衡是为RestTemplate 提供的能力。

类中注入了一个RestTemplate 集合,且用 @LoadBalanced 标注,这个注解只是一个标记注解,被 @Qualifier 注解标注,做了一个过滤,并没有处理@LoadBalanced的逻辑。

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

}

接下来的代码 生成了 LoadBalancerRequestFactory,loadBalancerInterceptor 和restTemplateCustomizer

@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)
@ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")
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);
      };
   }

}

上面生成了LoadBalancerInterceptor,并且在restTemplateCustomizer 中调用将LoadBalancerInterceptor设置给restTemplate,LoadBalancerInterceptor用来对http调用进行拦截,上一篇分析restTemplate时,看到过判断interceptor存在是走interceptor的方法。

2、LoadBalancerClient 接口

public interface LoadBalancerClient extends ServiceInstanceChooser {

	//用服务实例执行请求
   <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;

   <T> T execute(String serviceId, ServiceInstance serviceInstance,
         LoadBalancerRequest<T> request) throws IOException;

	//构建URI、
   URI reconstructURI(ServiceInstance instance, URI original);

}
public interface ServiceInstanceChooser {
	//根据serviceId 选择服务实例
	ServiceInstance choose(String serviceId);

}

3、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) {
      // for backwards compatibility
      this(loadBalancer, new LoadBalancerRequestFactory(loadBalancer));
   }

   @Override
   public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
         final ClientHttpRequestExecution execution) throws IOException {
      final URI originalUri = request.getURI();
      String serviceName = originalUri.getHost();
      Assert.state(serviceName != null,
            "Request URI does not contain a valid hostname: " + originalUri);
      return this.loadBalancer.execute(serviceName,
            this.requestFactory.createRequest(request, body, execution));
   }

}

LoadBalancerInterceptor 中有LoadBalancerClient ,LoadBalancerRequestFactory在构造LoadBalancerInterceptor 时会设置这两个成员。

当LoadBalancerInterceptor 拦截http请求时,执行intercept 方法,这是执行loadBalancer.execute方法,根据serviceName选择服务实例进行请求。

4、LoadBalancerRequestFactory

public class LoadBalancerRequestFactory {

   private LoadBalancerClient loadBalancer;

   private List<LoadBalancerRequestTransformer> transformers;

   public LoadBalancerRequestFactory(LoadBalancerClient loadBalancer,
         List<LoadBalancerRequestTransformer> transformers) {
      this.loadBalancer = loadBalancer;
      this.transformers = transformers;
   }

   public LoadBalancerRequestFactory(LoadBalancerClient loadBalancer) {
      this.loadBalancer = loadBalancer;
   }

   public LoadBalancerRequest<ClientHttpResponse> createRequest(
         final HttpRequest request, final byte[] body,
         final ClientHttpRequestExecution execution) {
      return instance -> {
         HttpRequest serviceRequest = new ServiceRequestWrapper(request, instance,
               this.loadBalancer);
         if (this.transformers != null) {
            for (LoadBalancerRequestTransformer transformer : this.transformers) {
               serviceRequest = transformer.transformRequest(serviceRequest,
                     instance);
            }
         }
         return execution.execute(serviceRequest, body);
      };
   }

}

LoadBalancerRequestFactory会具体执行request请求。

5、接上篇restTemplate,看一下执行流程。

//InterceptingClientHttpRequest.InterceptingRequestExecution#execute
protected final ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
    //创建一个拦截器执行器
   InterceptingRequestExecution requestExecution = new InterceptingRequestExecution();
    //执行
   return requestExecution.execute(this, bufferedOutput);
}
//org.springframework.http.client.InterceptingClientHttpRequest.InterceptingRequestExecution#execute
public ClientHttpResponse execute(HttpRequest request, byte[] body) throws IOException {
      //执行拦截器的方法
      if (this.iterator.hasNext()) {
         ClientHttpRequestInterceptor nextInterceptor = this.iterator.next();
         return nextInterceptor.intercept(request, body, this);
      }
      else {
         HttpMethod method = request.getMethod();
         Assert.state(method != null, "No standard HTTP method");
         ClientHttpRequest delegate = requestFactory.createRequest(request.getURI(), method);
         request.getHeaders().forEach((key, value) -> delegate.getHeaders().addAll(key, value));
         if (body.length > 0) {
            if (delegate instanceof StreamingHttpOutputMessage) {
               StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) delegate;
               streamingOutputMessage.setBody(outputStream -> StreamUtils.copy(body, outputStream));
            }
            else {
               StreamUtils.copy(body, delegate.getBody());
            }
         }
         return delegate.execute();
      }
   }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值