专业的编程技术博客社区

网站首页 > 博客文章 正文

聊聊spring cloud的AsyncLoadBalancerAutoConfiguration

baijin 2024-09-20 12:33:26 博客文章 3 ℃ 0 评论

本文主要研究一下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。

doc

  • 3.4 Spring WebClient as a Load Balancer Client

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表