关于spring cloud feign使用http get请求超时会重试一次的问题

一次feign调用流程:

1.--->注解@feignclient被包装成FeignClientFactoryBean

2.---> HystrixInvocationHandler.invoke

3.--->HystrixCommand.run

4.--->SynchronousMethodHandler.invoke

5.--->DependencyFeignClientAutoConfiguration.dependencyBasedFeignClient得到LoadBalancerFeignClient后

6.--->LoadBalancerFeignClient.execute  : 里面有个delegate=Client.Default

7.--->feignLoadBalancer.executeWithLoadBalancer (做一些ribbon负载均衡处理,选择一个server)

      a、创建LoadBalancerCommand command = buildLoadBalancerCommand(request, requestConfig)会指定重试RequestSpecificRetryHandler调用AbstractLoadBalancingClient.getRequestSpecificRetryHandler,代码如下:

@Override

public RequestSpecificRetryHandler getRequestSpecificRetryHandler(

final S request, final IClientConfig requestConfig) {

if (this.okToRetryOnAllOperations) {

return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(),

            requestConfig);

  }

if (!request.getContext().getMethod().equals("GET")) {//如果是post请求默认okToRetryOnAllErrors=false

return new RequestSpecificRetryHandler(true, false, this.getRetryHandler(),

            requestConfig);

  }

else {// 如果是get请求默认okToRetryOnAllErrors=true,这里就导致get请求超时会重试一次

return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(),

            requestConfig);

  }

}

b.超时异常重试会判断重试策略,进而判断异常是不是可重试的异常,代码如下:

private Func2 retryPolicy(final int maxRetrys, final boolean same) {

return new Func2() {

@Override

        public Booleancall(Integer tryCount, Throwable e) {

if (einstanceof AbortExecutionException) {

return false;

            }

if (tryCount >maxRetrys) {

return false;

            }

if (e.getCause() !=null && einstanceof RuntimeException) {

e = e.getCause();

            }

return retryHandler.isRetriableException(e, same);

        }

};

}

c.判断异常是不是可重试的异常,调用RequestSpecificRetryHandler.isRetriableException

@Override

public boolean isRetriableException(Throwable e, boolean sameServer) {

if (okToRetryOnAllErrors) {

return true;

    }

else if (einstanceof ClientException) {

ClientException ce = (ClientException) e;

        if (ce.getErrorType() == ClientException.ErrorType.SERVER_THROTTLED) {

return !sameServer;

        }else {

return false;

        }

}

else  {

return okToRetryOnConnectErrors && isConnectionException(e);

    }

}


8.--->LoadBalancerCommand.submit(ServerOperation operation) ---->operation.call{---------包含重试逻辑

AbstractLoadBalancerAwareClient.this.execute(requestForServer, requestConfig) ------------选择好server后,调用委托实例delegate的Client.execute方法,这时才是真正调用http请求

}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容