序
本文主要研究一下AsyncLoadBalancerAutoConfiguration
AsyncLoadBalancerAutoConfiguration
spring-cloud-commons-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/client/loadbalancer/AsyncLoadBalancerAutoConfiguration.java
/**
* Auto configuration for Ribbon (client side load balancing).
*
* @author Rob Worsnop
*/
@Configuration
@ConditionalOnBean(LoadBalancerClient.class)
@ConditionalOnClass(AsyncRestTemplate.class)
public class AsyncLoadBalancerAutoConfiguration {
@Configuration
static class AsyncRestTemplateCustomizerConfig {
@LoadBalanced
@Autowired(required = false)
private List<AsyncRestTemplate> restTemplates = Collections.emptyList();
@Bean
public SmartInitializingSingleton loadBalancedAsyncRestTemplateInitializer(
final List<AsyncRestTemplateCustomizer> customizers) {
return new SmartInitializingSingleton() {
@Override
public void afterSingletonsInstantiated() {
for (AsyncRestTemplate restTemplate : AsyncRestTemplateCustomizerConfig.this.restTemplates) {
for (AsyncRestTemplateCustomizer customizer : customizers) {
customizer.customize(restTemplate);
}
}
}
};
}
}
@Configuration
static class LoadBalancerInterceptorConfig {
@Bean
public AsyncLoadBalancerInterceptor asyncLoadBalancerInterceptor(LoadBalancerClient loadBalancerClient) {
return new AsyncLoadBalancerInterceptor(loadBalancerClient);
}
@Bean
public AsyncRestTemplateCustomizer asyncRestTemplateCustomizer(
final AsyncLoadBalancerInterceptor loadBalancerInterceptor) {
return new AsyncRestTemplateCustomizer() {
@Override
public void customize(AsyncRestTemplate restTemplate) {
List<AsyncClientHttpRequestInterceptor> list = new ArrayList<>(
restTemplate.getInterceptors());
list.add(loadBalancerInterceptor);
restTemplate.setInterceptors(list);
}
};
}
}
}
- 这里创建一个AsyncRestTemplateCustomizerConfig,用于加载AsyncRestTemplateCustomizer
- 还有一个LoadBalancerInterceptorConfig,配置了AsyncLoadBalancerInterceptor及AsyncRestTemplateCustomizer
AsyncRestTemplateCustomizer
spring-cloud-commons-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/client/loadbalancer/AsyncRestTemplateCustomizer.java
public interface AsyncRestTemplateCustomizer {
void customize(AsyncRestTemplate restTemplate);
}
- 这里采用匿名类实现,主要就是设置AsyncClientHttpRequestInterceptor
AsyncClientHttpRequestInterceptor
spring-cloud-commons-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/client/loadbalancer/AsyncLoadBalancerInterceptor.java
public class AsyncLoadBalancerInterceptor implements AsyncClientHttpRequestInterceptor {
private LoadBalancerClient loadBalancer;
public AsyncLoadBalancerInterceptor(LoadBalancerClient loadBalancer) {
this.loadBalancer = loadBalancer;
}
@Override
public ListenableFuture<ClientHttpResponse> intercept(final HttpRequest request, final byte[] body,
final AsyncClientHttpRequestExecution execution) throws IOException {
final URI originalUri = request.getURI();
String serviceName = originalUri.getHost();
return this.loadBalancer.execute(serviceName,
new LoadBalancerRequest<ListenableFuture<ClientHttpResponse>>() {
@Override
public ListenableFuture<ClientHttpResponse> apply(final ServiceInstance instance)
throws Exception {
HttpRequest serviceRequest = new ServiceRequestWrapper(request,
instance, loadBalancer);
return execution.executeAsync(serviceRequest, body);
}
});
}
}
- 这个拦截器从url获取serviceName,然后调用loadBalancer.execute方法
- 这里构造的LoadBalancerRequest,采用ServiceRequestWrapper,调用的是execution.executeAsync
AbstractAsyncClientHttpRequest
spring-web-5.0.7.RELEASE-sources.jar!/org/springframework/http/client/AbstractAsyncClientHttpRequest.java
/**
* Abstract base for {@link AsyncClientHttpRequest} that makes sure that headers and body
* are not written multiple times.
*
* @author Arjen Poutsma
* @since 4.0
* @deprecated as of Spring 5.0, in favor of {@link org.springframework.http.client.reactive.AbstractClientHttpRequest}
*/
@Deprecated
abstract class AbstractAsyncClientHttpRequest implements AsyncClientHttpRequest {
private final HttpHeaders headers = new HttpHeaders();
private boolean executed = false;
@Override
public final HttpHeaders getHeaders() {
return (this.executed ? HttpHeaders.readOnlyHttpHeaders(this.headers) : this.headers);
}
@Override
public final OutputStream getBody() throws IOException {
assertNotExecuted();
return getBodyInternal(this.headers);
}
@Override
public ListenableFuture<ClientHttpResponse> executeAsync() throws IOException {
assertNotExecuted();
ListenableFuture<ClientHttpResponse> result = executeInternal(this.headers);
this.executed = true;
return result;
}
/**
* Asserts that this request has not been {@linkplain #executeAsync() executed} yet.
* @throws IllegalStateException if this request has been executed
*/
protected void assertNotExecuted() {
Assert.state(!this.executed, "ClientHttpRequest already executed");
}
/**
* Abstract template method that returns the body.
* @param headers the HTTP headers
* @return the body output stream
*/
protected abstract OutputStream getBodyInternal(HttpHeaders headers) throws IOException;
/**
* Abstract template method that writes the given headers and content to the HTTP request.
* @param headers the HTTP headers
* @return the response object for the executed request
*/
protected abstract ListenableFuture<ClientHttpResponse> executeInternal(HttpHeaders headers)
throws IOException;
}
- 这个executeAsync的委托给子类的executeInternal实现
- 主要有SimpleStreamingAsyncClientHttpRequest、Netty4ClientHttpRequest两个实现
SimpleStreamingAsyncClientHttpRequest
spring-web-5.0.7.RELEASE-sources.jar!/org/springframework/http/client/SimpleStreamingAsyncClientHttpRequest.java
- 主要使用的是jdk的HttpURLConnection来实现
Netty4ClientHttpRequest
spring-web-5.0.7.RELEASE-sources.jar!/org/springframework/http/client/Netty4ClientHttpRequest.java
- 使用netty的bootstrap.connect进行请求
小结
AsyncLoadBalancerAutoConfiguration使用的AsyncClientHttpRequest及其实现类都被标记为废弃,spring 5之后推荐使用webClient。