Springcloud-loadbalancer-05

311 阅读3分钟

png5.png 👉最后我们再看下BlockingLoadBalancerClientAutoConfiguration

其实从以前介绍中我们其实可以猜到,它就是获取服务实例的。

/**
 * An autoconfiguration for {@link BlockingLoadBalancerClient}.
 *
 * @author Olga Maciaszek-Sharma
 * @author Gandhimathi Velusamy
 * @since 2.1.3
 */
@Configuration(proxyBeanMethods = false)
@LoadBalancerClients
@AutoConfigureAfter(LoadBalancerAutoConfiguration.class)
@AutoConfigureBefore({ org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration.class,
      AsyncLoadBalancerAutoConfiguration.class })
@ConditionalOnClass(RestTemplate.class)
public class BlockingLoadBalancerClientAutoConfiguration {

   @Bean
   @ConditionalOnBean(LoadBalancerClientFactory.class)
   @ConditionalOnMissingBean
   //创建阻塞式负载均衡客户端,它主要实现了LoadBalancerClient和ServiceInstanceChooser接口
   //用来选择ServiceInstance和执行request
   public LoadBalancerClient blockingLoadBalancerClient(LoadBalancerClientFactory loadBalancerClientFactory) {
      return new BlockingLoadBalancerClient(loadBalancerClientFactory);
   }

   @Bean
   @ConditionalOnBean(LoadBalancerClientFactory.class)
   @ConditionalOnMissingBean(LoadBalancerServiceInstanceCookieTransformer.class)
   public LoadBalancerServiceInstanceCookieTransformer loadBalancerServiceInstanceCookieTransformer(
         LoadBalancerClientFactory loadBalancerClientFactory) {
      return new LoadBalancerServiceInstanceCookieTransformer(loadBalancerClientFactory);
   }

   @Bean
   @ConditionalOnMissingBean(XForwardedHeadersTransformer.class)
   @ConditionalOnBean(LoadBalancerClientFactory.class)
   public XForwardedHeadersTransformer xForwarderHeadersTransformer(
         LoadBalancerClientFactory loadBalancerClientFactory) {
      return new XForwardedHeadersTransformer(loadBalancerClientFactory);
   }

   @Configuration
   @ConditionalOnClass(RetryTemplate.class)
   @EnableConfigurationProperties(LoadBalancerClientsProperties.class)
   //创建loadBalancer重试策略
   protected static class BlockingLoadBalancerRetryConfig {

      @Bean
      @ConditionalOnMissingBean
      LoadBalancedRetryFactory loadBalancedRetryFactory(
            ReactiveLoadBalancer.Factory<ServiceInstance> loadBalancerFactory) {
         return new BlockingLoadBalancedRetryFactory(loadBalancerFactory);
      }

   }

}

从描述中我们可以看出它是BlockingLoadBalancerClient的配置类,URL如下:

从以上类图我们很清楚的看出BlockingLoadBalancerClient主要具备了使用chooose方法选择实例,以及使用execute方法执行请求。

/**
 * The default {@link LoadBalancerClient} implementation.
 *
 * @author Olga Maciaszek-Sharma
 * @since 2.2.0
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public class BlockingLoadBalancerClient implements LoadBalancerClient {
		
   private final ReactiveLoadBalancer.Factory<ServiceInstance> loadBalancerClientFactory;

   /**
    * @deprecated in favour of
    * {@link BlockingLoadBalancerClient#BlockingLoadBalancerClient(ReactiveLoadBalancer.Factory)}
    */
   @Deprecated
   public BlockingLoadBalancerClient(LoadBalancerClientFactory loadBalancerClientFactory,
         LoadBalancerProperties properties) {
      this.loadBalancerClientFactory = loadBalancerClientFactory;
   }

   public BlockingLoadBalancerClient(ReactiveLoadBalancer.Factory<ServiceInstance> loadBalancerClientFactory) {
      this.loadBalancerClientFactory = loadBalancerClientFactory;
   }

   @Override
   public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {
      String hint = getHint(serviceId);
      LoadBalancerRequestAdapter<T, DefaultRequestContext> lbRequest = new LoadBalancerRequestAdapter<>(request,
            new DefaultRequestContext(request, hint));
      Set<LoadBalancerLifecycle> supportedLifecycleProcessors = getSupportedLifecycleProcessors(serviceId);
      supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStart(lbRequest));
      //选择服务
      ServiceInstance serviceInstance = choose(serviceId, lbRequest);
      if (serviceInstance == null) {
         supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onComplete(
               new CompletionContext<>(CompletionContext.Status.DISCARD, lbRequest, new EmptyResponse())));
         throw new IllegalStateException("No instances available for " + serviceId);
      }
      return execute(serviceId, serviceInstance, lbRequest);
   }

   @Override
   public <T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request)
         throws IOException {
      DefaultResponse defaultResponse = new DefaultResponse(serviceInstance);
      Set<LoadBalancerLifecycle> supportedLifecycleProcessors = getSupportedLifecycleProcessors(serviceId);
      Request lbRequest = request instanceof Request ? (Request) request : new DefaultRequest<>();
      supportedLifecycleProcessors
            .forEach(lifecycle -> lifecycle.onStartRequest(lbRequest, new DefaultResponse(serviceInstance)));
      try {
         T response = request.apply(serviceInstance);
         Object clientResponse = getClientResponse(response);
         supportedLifecycleProcessors
               .forEach(lifecycle -> lifecycle.onComplete(new CompletionContext<>(CompletionContext.Status.SUCCESS,
                     lbRequest, defaultResponse, clientResponse)));
         return response;
      }
      catch (IOException iOException) {
         supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onComplete(
               new CompletionContext<>(CompletionContext.Status.FAILED, iOException, lbRequest, defaultResponse)));
         throw iOException;
      }
      catch (Exception exception) {
         supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onComplete(
               new CompletionContext<>(CompletionContext.Status.FAILED, exception, lbRequest, defaultResponse)));
         ReflectionUtils.rethrowRuntimeException(exception);
      }
      return null;
   }

   private <T> Object getClientResponse(T response) {
      ClientHttpResponse clientHttpResponse = null;
      if (response instanceof ClientHttpResponse) {
         clientHttpResponse = (ClientHttpResponse) response;
      }
      if (clientHttpResponse != null) {
         try {
            return new ResponseData(clientHttpResponse, null);
         }
         catch (IOException ignored) {
         }
      }
      return response;
   }

   private Set<LoadBalancerLifecycle> getSupportedLifecycleProcessors(String serviceId) {
      return LoadBalancerLifecycleValidator.getSupportedLifecycleProcessors(
            loadBalancerClientFactory.getInstances(serviceId, LoadBalancerLifecycle.class),
            DefaultRequestContext.class, Object.class, ServiceInstance.class);
   }

   @Override
   public URI reconstructURI(ServiceInstance serviceInstance, URI original) {
      return LoadBalancerUriTools.reconstructURI(serviceInstance, original);
   }

   @Override
   public ServiceInstance choose(String serviceId) {
      return choose(serviceId, REQUEST);
   }

   @Override
   //利用不同的负载均衡客户端选择不同的服务
   public <T> ServiceInstance choose(String serviceId, Request<T> request) {
      ReactiveLoadBalancer<ServiceInstance> loadBalancer = loadBalancerClientFactory.getInstance(serviceId);
      if (loadBalancer == null) {
         return null;
      }
      //具体负载均衡客服端的选择逻辑,默认是RoundRobinLoadBalance方式的负载均衡
      Response<ServiceInstance> loadBalancerResponse = Mono.from(loadBalancer.choose(request)).block();
      if (loadBalancerResponse == null) {
         return null;
      }
      return loadBalancerResponse.getServer();
   }

   private String getHint(String serviceId) {
      LoadBalancerProperties properties = loadBalancerClientFactory.getProperties(serviceId);
      String defaultHint = properties.getHint().getOrDefault("default", "default");
      String hintPropertyValue = properties.getHint().get(serviceId);
      return hintPropertyValue != null ? hintPropertyValue : defaultHint;
   }

}

先看下如何选择服务实例choose,有了前面的知识,我们们看这个方法是不是很熟悉,它先在loadBalancerClientFactory获取一个负载均衡策略,默认的有随机和轮训,并调用该负载均衡的choose方法,具体上面已经介绍了,选择完成之后我们只需取出选择的服务实例就行了,最后在调用execute执行就行了。

@Override
public <T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request)
      throws IOException {
   DefaultResponse defaultResponse = new DefaultResponse(serviceInstance);
   Set<LoadBalancerLifecycle> supportedLifecycleProcessors = getSupportedLifecycleProcessors(serviceId);
   Request lbRequest = request instanceof Request ? (Request) request : new DefaultRequest<>();
   supportedLifecycleProcessors
         .forEach(lifecycle -> lifecycle.onStartRequest(lbRequest, new DefaultResponse(serviceInstance)));
   try {
      T response = request.apply(serviceInstance);
      Object clientResponse = getClientResponse(response);
      supportedLifecycleProcessors
            .forEach(lifecycle -> lifecycle.onComplete(new CompletionContext<>(CompletionContext.Status.SUCCESS,
                  lbRequest, defaultResponse, clientResponse)));
      return response;
   }
   catch (IOException iOException) {
      supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onComplete(
            new CompletionContext<>(CompletionContext.Status.FAILED, iOException, lbRequest, defaultResponse)));
      throw iOException;
   }
   catch (Exception exception) {
      supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onComplete(
            new CompletionContext<>(CompletionContext.Status.FAILED, exception, lbRequest, defaultResponse)));
      ReflectionUtils.rethrowRuntimeException(exception);
   }
   return null;
}

我们具体看下T response = request.apply(serviceInstance);方法。

/**
 * Simple interface used by LoadBalancerClient to apply metrics or pre and post actions
 * around load balancer requests.
 *
 * @param <T> type of the response
 * @author Spencer Gibb
 */
public interface LoadBalancerRequest<T> {

   T apply(ServiceInstance instance) throws Exception;

}

execute.png 我们看下LoadBalancerRequestFactory.createRequest方法

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);
   };
}

可以看出在execution.execute(serviceRequest, body);执行请求。

我们在看下ClientHttpRequestExecution接口的实现InterceptingRequestExecution.execute

@Override
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();
   }
}

这里可以看到this.iterator,这其实就是拦截器,如果你debug的话,其中有个负载均衡拦截器,上面介绍过哦,它加入了RestTemplate中去了,使用该拦截器的intercept方法,等拦截器的intercept执行完成之后,就会执行delegate.execute()方法

,我们看下ClientHttpRequest httpclientrequest.png 可以看出它可以使用Netty或者Http客户端发起请求。

至此我们就说完了😇,等下还有个时序图,不搞了,直接在 restTemplate.getForEntity打个断点就可以了,最后在看下第一张图。 loadbalancer.drawio.png