共计 4013 个字符,预计需要花费 11 分钟才能阅读完成。
序
本文主要研究一下 spring cloud 的 RetryableFeignLoadBalancer
RetryableFeignLoadBalancer
spring-cloud-openfeign-core-2.2.0.M1-sources.jar!/org/springframework/cloud/openfeign/ribbon/RetryableFeignLoadBalancer.java
public class RetryableFeignLoadBalancer extends FeignLoadBalancer
implements ServiceInstanceChooser {
private final LoadBalancedRetryFactory loadBalancedRetryFactory;
public RetryableFeignLoadBalancer(ILoadBalancer lb, IClientConfig clientConfig,
ServerIntrospector serverIntrospector,
LoadBalancedRetryFactory loadBalancedRetryFactory) {super(lb, clientConfig, serverIntrospector);
this.loadBalancedRetryFactory = loadBalancedRetryFactory;
this.setRetryHandler(new DefaultLoadBalancerRetryHandler(clientConfig));
}
@Override
public RibbonResponse execute(final RibbonRequest request,
IClientConfig configOverride) throws IOException {
final Request.Options options;
if (configOverride != null) {RibbonProperties ribbon = RibbonProperties.from(configOverride);
options = new Request.Options(ribbon.connectTimeout(this.connectTimeout),
ribbon.readTimeout(this.readTimeout));
}
else {options = new Request.Options(this.connectTimeout, this.readTimeout);
}
final LoadBalancedRetryPolicy retryPolicy = this.loadBalancedRetryFactory
.createRetryPolicy(this.getClientName(), this);
RetryTemplate retryTemplate = new RetryTemplate();
BackOffPolicy backOffPolicy = this.loadBalancedRetryFactory
.createBackOffPolicy(this.getClientName());
retryTemplate.setBackOffPolicy(backOffPolicy == null ? new NoBackOffPolicy() : backOffPolicy);
RetryListener[] retryListeners = this.loadBalancedRetryFactory
.createRetryListeners(this.getClientName());
if (retryListeners != null && retryListeners.length != 0) {retryTemplate.setListeners(retryListeners);
}
retryTemplate.setRetryPolicy(retryPolicy == null ? new NeverRetryPolicy()
: new FeignRetryPolicy(request.toHttpRequest(), retryPolicy, this,
this.getClientName()));
return retryTemplate.execute(new RetryCallback<RibbonResponse, IOException>() {
@Override
public RibbonResponse doWithRetry(RetryContext retryContext)
throws IOException {
Request feignRequest = null;
// on retries the policy will choose the server and set it in the context
// extract the server and update the request being made
if (retryContext instanceof LoadBalancedRetryContext) {ServiceInstance service = ((LoadBalancedRetryContext) retryContext)
.getServiceInstance();
if (service != null) {feignRequest = ((RibbonRequest) request
.replaceUri(reconstructURIWithServer(new Server(service.getHost(), service.getPort()),
request.getUri()))).toRequest();}
}
if (feignRequest == null) {feignRequest = request.toRequest();
}
Response response = request.client().execute(feignRequest, options);
if (retryPolicy != null
&& retryPolicy.retryableStatusCode(response.status())) {byte[] byteArray = response.body() == null ? new byte[] {}
: StreamUtils
.copyToByteArray(response.body().asInputStream());
response.close();
throw new RibbonResponseStatusCodeException(
RetryableFeignLoadBalancer.this.clientName, response,
byteArray, request.getUri());
}
return new RibbonResponse(request.getUri(), response);
}
}, new LoadBalancedRecoveryCallback<RibbonResponse, Response>() {
@Override
protected RibbonResponse createResponse(Response response, URI uri) {return new RibbonResponse(uri, response);
}
});
}
@Override
public RequestSpecificRetryHandler getRequestSpecificRetryHandler(FeignLoadBalancer.RibbonRequest request, IClientConfig requestConfig) {return new RequestSpecificRetryHandler(false, false, this.getRetryHandler(),
requestConfig);
}
@Override
public ServiceInstance choose(String serviceId) {
return new RibbonLoadBalancerClient.RibbonServer(serviceId,
this.getLoadBalancer().chooseServer(serviceId));
}
}
- RetryableFeignLoadBalancer 继承了 FeignLoadBalancer,实现了 ServiceInstanceChooser 接口
- 其构造器根据 clientConfig 创建了 DefaultLoadBalancerRetryHandler;其 choose 方法使用的是 getLoadBalancer().chooseServer,最后通过 RibbonLoadBalancerClient.RibbonServer 包装返回
- 其 execute 方法首先创建了 LoadBalancedRetryPolicy,进而创建 retryTemplate,最后通过 retryTemplate.execute 来实现重试功能;其 RetryCallback 的 doWithRetry 方法在 retryContext 是 LoadBalancedRetryContext 的条件下会切换下一个 service 实例来进行重试
小结
RetryableFeignLoadBalancer 继承了 FeignLoadBalancer,对 execute 方法使用 retryTemplate 来实现重试,其中在 retryContext 是 LoadBalancedRetryContext 的条件下会切换下一个 service 实例来进行重试
doc
- RetryableFeignLoadBalancer
正文完