背景:
生产环境中发现很多调用滴滴侧接口出现Feign IOException异常的接口,打印出的超时时间跟我们apollo中配置的超时时间没有对应上,由此根据这个问题对项目代码进行进一步的排查发现,我们设置的超时时间并没有生效;
原因:
查询apollo配置发现,我们设置的超时时间是:
name | value |
---|---|
feign.okhttp.connection-timeout | 2000 |
feign.okhttp.read-timeout | 2000 |
但是在实际的过程中,这个参数并没有生效,查询OkHttpClient源码可以发现:
@Override
public feign.Response execute(feign.Request input, feign.Request.Options options)
throws IOException {
okhttp3.OkHttpClient requestScoped;
if (delegate.connectTimeoutMillis() != options.connectTimeoutMillis()
|| delegate.readTimeoutMillis() != options.readTimeoutMillis()) {
requestScoped = delegate.newBuilder()
.connectTimeout(options.connectTimeoutMillis(), TimeUnit.MILLISECONDS)
.readTimeout(options.readTimeoutMillis(), TimeUnit.MILLISECONDS)
.followRedirects(options.isFollowRedirects())
.build();
} else {
requestScoped = delegate;
}
Request request = toOkHttpRequest(input);
Response response = requestScoped.newCall(request).execute();
return toFeignResponse(response, input).toBuilder().request(input).build();
}
在实际的生产环境中生效的其实是feign.Request.Options 里面配置超时时间,查询内部源码发现默认设置的是10s,和60s
okhttpClient的官方issue也有对应的问题描述链接:https://github.com/OpenFeign/feign/issues/781
方案:
1.新增这2个参数:
feign.client.config.default.connect-timeout = 2000
feign.client.config.default.read-timeout = 2000
使线上设置的2s超时实际生效;
原因:
因为超时时间的优先级:hystrix>ribbon>okhttp,那么在实际生产环境中肯定首先生效的是hystrix,但这个触发的时候我们代码就进入量fallback中,所以按理说后面的超时时间应该设置的比hystrix略微小一点,
同时考虑到设置了这个时间会不会对线上业务有影响,确认后不存在影响,因为在实际生产环境中,2s后以及触发了熔断线程,即使接口后面返回,这次请求也失败了;所以判断该参数设置对线上业务没有影响;