小知识,大挑战!本文正在参与「程序员必备小知识」创作活动
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构造