LoadBalanced注解2

106 阅读2分钟

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

LoadBalancerClient会根据负载均衡请求和服务名执行真正的负载均衡操作

LoadBalancerClient接口:

public interface LoadBalancerClient extends ServiceInstanceChooser {

   /**
    * Executes 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.
    * @param <T> type of the response
    * @throws IOException in case of IO issues.
    * @return The result of the LoadBalancerRequest callback on the selected
    * ServiceInstance.
    */
   <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;

   /**
    * Executes request using a ServiceInstance from the LoadBalancer for the specified
    * service.
    * @param serviceId The service ID to look up the LoadBalancer.
    * @param serviceInstance The service to execute the request to.
    * @param request Allows implementations to execute pre and post actions, such as
    * incrementing metrics.
    * @param <T> type of the response
    * @throws IOException in case of IO issues.
    * @return The result of the LoadBalancerRequest callback on the selected
    * ServiceInstance.
    */
   <T> T execute(String serviceId, ServiceInstance serviceInstance,
         LoadBalancerRequest<T> request) throws IOException;

   /**
    * Creates a proper URI with a real host and port for systems to utilize. Some systems
    * use a URI with the logical service 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 service instance to reconstruct the URI
    * @param original A URI with the host as a logical service name.
    * @return A reconstructed URI.
    */
   URI reconstructURI(ServiceInstance instance, URI original);

}

reconstructURI方法用于重新构造URI

LoadBalancerRequest表示异常负载均衡请求,被LoadBalancerRequestFactory构造

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

}

构造出的负载均衡请求ServiceRequestWrapper,根据LoadBalancerRequestTransformer二次加工,然后执行execute方法

LoadBalancerClient的默认实现类是BlockingLoadBalancerClient,

public class BlockingLoadBalancerClient implements LoadBalancerClient {
    private final LoadBalancerClientFactory loadBalancerClientFactory;

    public BlockingLoadBalancerClient(LoadBalancerClientFactory loadBalancerClientFactory) {
        this.loadBalancerClientFactory = loadBalancerClientFactory;
    }

    public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {
        ServiceInstance serviceInstance = this.choose(serviceId);
        if (serviceInstance == null) {
            throw new IllegalStateException("No instances available for " + serviceId);
        } else {
            return this.execute(serviceId, serviceInstance, request);
        }
    }

    public <T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException {
        try {
            return request.apply(serviceInstance);
        } catch (IOException var5) {
            throw var5;
        } catch (Exception var6) {
            ReflectionUtils.rethrowRuntimeException(var6);
            return null;
        }
    }

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

    public ServiceInstance choose(String serviceId) {
        ReactiveLoadBalancer<ServiceInstance> loadBalancer = this.loadBalancerClientFactory.getInstance(serviceId);
        if (loadBalancer == null) {
            return null;
        } else {
            Response<ServiceInstance> loadBalancerResponse = (Response)Mono.from(loadBalancer.choose()).block();
            return loadBalancerResponse == null ? null : (ServiceInstance)loadBalancerResponse.getServer();
        }
    }
}

Spring Cloud LoadBalancer总结:

@LoadBalanced注解修饰RestTemplate后,根据RestTemplateCustomizer注解给RestTemplate做定制化操作。定制化操作一定含有一个LoadBalancerInterceptor

LoadBalancerInterceptor负载均衡拦截器背后通过LoadBalancerClient的execute方法完成最终的调用。execute需要两个参数,一个服务名,另一个是负载均衡请求LoadBalancerRequest,LoadBalancerRequest通过LoadBalancerRequestFactory构造