spring-cloud-netflix-ribbon学习笔记(二)LoadBalancerInterceptor的处理逻辑
上一篇讲到,Ribbon与Spring-Cloud整合以后,会给RestTemplate
加上一个LoadBalancerInterceptor
的拦截器,那么现在就来看看LoadBalancerInterceptor
里面的逻辑吧~话不多说,先上代码:
package org.springframework.cloud.client.loadbalancer;
import java.io.IOException;
import java.net.URI;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.Assert;
/**
* @author Spencer Gibb
* @author Dave Syer
* @author Ryan Baxter
* @author William Tran
*/
public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {
private LoadBalancerClient loadBalancer;
private LoadBalancerRequestFactory requestFactory;
public LoadBalancerInterceptor(LoadBalancerClient loadBalancer,
LoadBalancerRequestFactory requestFactory) {
this.loadBalancer = loadBalancer;
this.requestFactory = requestFactory;
}
public LoadBalancerInterceptor(LoadBalancerClient loadBalancer) {
// for backwards compatibility
this(loadBalancer, new LoadBalancerRequestFactory(loadBalancer));
}
@Override
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
final ClientHttpRequestExecution execution) throws IOException {
final URI originalUri = request.getURI();
String serviceName = originalUri.getHost();
Assert.state(serviceName != null,
"Request URI does not contain a valid hostname: " + originalUri);
return this.loadBalancer.execute(serviceName,
this.requestFactory.createRequest(request, body, execution));
}
}
第一步:
这里可以看到LoadBalancerInterceptor
有两个属性,一个是LoadBalancerClient
,其实现子类是org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient
;另一个是LoadBalancerRequestFactory
。而intercept
就是实际拦截的方法了。可以看到intercept
方法先是拿到了请求和uri和serviceName,并且在serviceName为null的情况下报了个错。接着就是使用LoadBalancerClient
来真正的执行请求方法。不过这里先不看它是怎么执行的,先抱着好奇的心态来看一下LoadBalancerRequestFactory
是怎么创建一个Request的。
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);
};
}
}
第二步:
这里可以看到createRequest
方法使用java8的lambda语法创建了一个匿名的LoadBalancerRequest
类,内部处理逻辑是: 先是把HttpRequest
包装成了ServiceRequestWrapper
,然后判断了transformers
为不为空,但是笔者发现这个接口好像在当前项目中没有实现类,而且看接口好像也是给HttpRequest
处理一下,接口方法:HttpRequest transformRequest(HttpRequest request, ServiceInstance instance);
,这里就先不管他了。最后执行了ClientHttpRequestExecution
的execute
方法。那我们在跟过去看一看。
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();
}
}
第三步:
这里就发现了很神奇的事了,一开始就来判断了是否还有下一个拦截器,如果有,就继续执行拦截器的逻辑,又回到了最开始的一步(LoadBalancerInterceptor.intercept方法
),否则就执行请求。
总结:
目前就知道了拦截器是怎么工作的,接下来就要看看看第一步中的(this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution));
)LoadBalancerClient的excute方法了。
自学咖网 » spring-cloud-netflix-ribbon学习笔记(二)LoadBalancerInterceptor的处理逻辑