本文主要研究一下spring cloud的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,对execute方法使用retryTemplate来实现重试,其中在retryContext是LoadBalancedRetryContext的条件下会切换下一个service实例来进行重试