java中timeout设置为0,spring-cloud服务网关中的Timeout设置

大家在初次使用spring-cloud的gateway的时候,肯定会被里面各种的Timeout搞得晕头转向。hytrix有设置,ribbon也有。我们一开始也是乱设一桶,Github上各种项目里也没几个设置正确的。对Timeout的研究源于一次log中的warning

The Hystrix timeout of 60000 ms for the command “foo” is set lower than the combination of the Ribbon read and connect timeout, 200000ms.

hytrix超时时间

log出自AbstractRibbonCommand.java,那么索性研究一下源码。

假设:

这里gateway会请求一个serviceName=foo的服务

protected static int getHystrixTimeout(IClientConfig config, String commandKey) {

int ribbonTimeout = getRibbonTimeout(config, commandKey);

DynamicPropertyFactory dynamicPropertyFactory = DynamicPropertyFactory.getInstance();

// 获取默认的hytrix超时时间

int defaultHystrixTimeout = dynamicPropertyFactory.getIntProperty("hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds",

0).get();

// 获取具体服务的hytrix超时时间,这里应该是hystrix.command.foo.execution.isolation.thread.timeoutInMilliseconds

int commandHystrixTimeout = dynamicPropertyFactory.getIntProperty("hystrix.command." + commandKey + ".execution.isolation.thread.timeoutInMilliseconds",

0).get();

int hystrixTimeout;

// hystrixTimeout的优先级是 具体服务的hytrix超时时间 > 默认的hytrix超时时间 > ribbon超时时间

if(commandHystrixTimeout > 0) {

hystrixTimeout = commandHystrixTimeout;

}

else if(defaultHystrixTimeout > 0) {

hystrixTimeout = defaultHystrixTimeout;

} else {

hystrixTimeout = ribbonTimeout;

}

// 如果默认的或者具体服务的hytrix超时时间小于ribbon超时时间就会警告

if(hystrixTimeout < ribbonTimeout) {

LOGGER.warn("The Hystrix timeout of " + hystrixTimeout + "ms for the command " + commandKey +

" is set lower than the combination of the Ribbon read and connect timeout, " + ribbonTimeout + "ms.");

}

return hystrixTimeout;

}

紧接着,看一下我们的配置是什么

hystrix:

command:

default:

execution:

isolation:

thread:

timeoutInMilliseconds: 60000

ribbon:

ReadTimeout: 50000

ConnectTimeout: 50000

MaxAutoRetries: 0

MaxAutoRetriesNextServer: 1

ribbon超时时间

这里ribbon的超时时间是50000ms,那么为什么log中写的ribbon时间是200000ms?

继续分析源码:

protected static int getRibbonTimeout(IClientConfig config, String commandKey) {

int ribbonTimeout;

// 这是比较异常的情况,不说

if (config == null) {

ribbonTimeout = RibbonClientConfiguration.DEFAULT_READ_TIMEOUT + RibbonClientConfiguration.DEFAULT_CONNECT_TIMEOUT;

} else {

// 这里获取了四个参数,ReadTimeout,ConnectTimeout,MaxAutoRetries, MaxAutoRetriesNextServer

int ribbonReadTimeout = getTimeout(config, commandKey, "ReadTimeout",

IClientConfigKey.Keys.ReadTimeout, RibbonClientConfiguration.DEFAULT_READ_TIMEOUT);

int ribbonConnectTimeout = getTimeout(config, commandKey, "ConnectTimeout",

IClientConfigKey.Keys.ConnectTimeout, RibbonClientConfiguration.DEFAULT_CONNECT_TIMEOUT);

int maxAutoRetries = getTimeout(config, commandKey, "MaxAutoRetries",

IClientConfigKey.Keys.MaxAutoRetries, DefaultClientConfigImpl.DEFAULT_MAX_AUTO_RETRIES);

int maxAutoRetriesNextServer = getTimeout(config, commandKey, "MaxAutoRetriesNextServer",

IClientConfigKey.Keys.MaxAutoRetriesNextServer, DefaultClientConfigImpl.DEFAULT_MAX_AUTO_RETRIES_NEXT_SERVER);

// 原来ribbonTimeout的计算方法在这里,以上文的设置为例

// ribbonTimeout = (50000 + 50000) * (0 + 1) * (1 + 1) = 200000

ribbonTimeout = (ribbonReadTimeout + ribbonConnectTimeout) * (maxAutoRetries + 1) * (maxAutoRetriesNextServer + 1);

}

return ribbonTimeout;

}

可以看到ribbonTimeout是一个总时间,所以从逻辑上来讲,作者希望hystrixTimeout要大于ribbonTimeout,否则hystrix熔断了以后,ribbon的重试就都没有意义了。

ribbon单服务设置

到这里最前面的疑问已经解开了,但是hytrix可以分服务设置timeout,ribbon可不可以? 源码走起,这里看的文件是DefaultClientConfigImpl.java

// 这是获取配置的入口方法,如果是null,那么用默认值

// 所有ribbon的默认值的都在该类中设置了,可以自己看一下

public T get(IClientConfigKey key, T defaultValue) {

T value = get(key);

if (value == null) {

value = defaultValue;

}

return value;

}

// 这是核心方法

protected Object getProperty(String key) {

if (enableDynamicProperties) {

String dynamicValue = null;

DynamicStringProperty dynamicProperty = dynamicProperties.get(key);

// dynamicProperties其实是一个缓存,首次访问foo服务的时候会加载

if (dynamicProperty != null) {

dynamicValue = dynamicProperty.get();

}

// 如果缓存没有,那么就再获取一次,注意这里的getConfigKey(key)是生成key的方法

if (dynamicValue == null) {

dynamicValue = DynamicProperty.getInstance(getConfigKey(key)).getString();

// 如果还是没有取默认值,getDefaultPropName(key)生成key的方法

if (dynamicValue == null) {

dynamicValue = DynamicProperty.getInstance(getDefaultPropName(key)).getString();

}

}

if (dynamicValue != null) {

return dynamicValue;

}

}

return properties.get(key);

}

以我们的服务为例:

getConfigKey(key) returns foo.ribbon.ReadTimeout

getDefaultPropName(key) returns ribbon.ReadTimeout

一目了然,{serviceName}.ribbon.{propertyName}就可以了。

小结

感觉ribbon和hytrix的配置获取源码略微有点乱,所以也导致大家在设置的时候有些无所适从。spring-cloud的代码一直在迭代,无论github上还是文档可能都相对滞后,这时候阅读源码并且动手debug一下是最能接近事实真相的了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值