最近项目中项目组后端架构采用springcloud 微服务模式架构,小伙伴们在使用的过程中,反馈有些服务调用,一直报超时,错误为 feign.RetryableException: Read timed out executing 小伙伴们通过各种百度,搜出来的很多坑爹的文章误导大家。迫不得已,翻了下源码。具体的源码如下
设置默认超时时间的地方在 FeignClientFactoryBean类中
protected Feign.Builder feign(FeignContext context) {
FeignLoggerFactory loggerFactory = get(context, FeignLoggerFactory.class);
Logger logger = loggerFactory.create(this.type);
// @formatter:off
Feign.Builder builder = get(context, Feign.Builder.class)
// required values
.logger(logger)
.encoder(get(context, Encoder.class))
.decoder(get(context, Decoder.class))
.contract(get(context, Contract.class));
// @formatter:on
configureFeign(context, builder);
return builder;
}
主要看 Feign.Builder.class 中的 new Options() ,这里设置默认值,构造起设置的参数如下
public Options() {
this(10 *1000,60 *1000);
}
以上为默认值:
如果配置文件设置了则使用配置文件中的代码如下
protected void configureFeign(FeignContext context, Feign.Builder builder) {
FeignClientProperties properties =applicationContext.getBean(FeignClientProperties.class);
if (properties !=null) {
if (properties.isDefaultToProperties()) {
configureUsingConfiguration(context, builder);
configureUsingProperties(properties.getConfig().get(properties.getDefaultConfig()), builder);
configureUsingProperties(properties.getConfig().get(this.name), builder);
}else {
configureUsingProperties(properties.getConfig().get(properties.getDefaultConfig()), builder);
configureUsingProperties(properties.getConfig().get(this.name), builder);
configureUsingConfiguration(context, builder);
}
}else {
configureUsingConfiguration(context, builder);
}
}
看这块代码 configureUsingProperties(properties.getConfig().get(properties.getDefaultConfig()), builder);
进去代码如下:
protected void configureUsingProperties(FeignClientProperties.FeignClientConfiguration config, Feign.Builder builder) {
if (config ==null) {
return;
}
if (config.getLoggerLevel() !=null) {
builder.logLevel(config.getLoggerLevel());
}
if (config.getConnectTimeout() !=null && config.getReadTimeout() !=null) {
builder.options(new Request.Options(config.getConnectTimeout(), config.getReadTimeout()));
}
if (config.getRetryer() !=null) {
Retryer retryer = getOrInstantiate(config.getRetryer());
builder.retryer(retryer);
}
if (config.getErrorDecoder() !=null) {
ErrorDecoder errorDecoder = getOrInstantiate(config.getErrorDecoder());
builder.errorDecoder(errorDecoder);
}
if (config.getRequestInterceptors() !=null && !config.getRequestInterceptors().isEmpty()) {
// this will add request interceptor to builder, not replace existing
for (Class bean : config.getRequestInterceptors()) {
RequestInterceptor interceptor = getOrInstantiate(bean);
builder.requestInterceptor(interceptor);
}
}
if (config.getDecode404() !=null) {
if (config.getDecode404()) {
builder.decode404();
}
}
if (Objects.nonNull(config.getEncoder())) {
builder.encoder(getOrInstantiate(config.getEncoder()));
}
if (Objects.nonNull(config.getDecoder())) {
builder.decoder(getOrInstantiate(config.getDecoder()));
}
if (Objects.nonNull(config.getContract())) {
builder.contract(getOrInstantiate(config.getContract()));
}
}
以上代码比较好理解,如果配置了超时时间则取配置文件中的,否则使用默认的
所以在项目中加以下配置,超时问题解决:
feign.client.config.default.ReadTimeout=60000
feign.client.config.default.ConnectTimeout=60000
如果有通过注解方式进行配置的,验证完晚点再更新文章给大家