前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >聊聊spring cloud的RetryableFeignLoadBalancer

聊聊spring cloud的RetryableFeignLoadBalancer

原创
作者头像
code4it
修改2019-07-15 11:13:56
7100
修改2019-07-15 11:13:56
举报
文章被收录于专栏:码匠的流水账码匠的流水账

本文主要研究一下spring cloud的RetryableFeignLoadBalancer

RetryableFeignLoadBalancer

spring-cloud-openfeign-core-2.2.0.M1-sources.jar!/org/springframework/cloud/openfeign/ribbon/RetryableFeignLoadBalancer.java

代码语言:javascript
复制
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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • RetryableFeignLoadBalancer
  • 小结
  • doc
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档