springcloud中Ribbon常常用来做负载均衡,其超时时间可以用以下公式来计算。
RibbonTime=(ReadTimeout+ConnectTimeout)*(1+MaxAutoRetries)*(1+MaxAutoRetriesNextServer)
ReadTimeout:处理超时时间
ConnectTimeout:连接建立超时时间
MaxAutoRetries:当前服务器的重试次数(不包括当前请求)
MaxAutoRetriesNextServer:负载到其他服务器的请求次数
上图中T1指网关转发请求到服务A时,总共的超时时间。
T2指服务A调用服务B的超时时间,如果服务是采用Feign,则代表是FeignClient的超时时间。
一、服务A到服务B的超时时间测试
服务A中FeignClient的超时配置如下(其中网关的超时时间是60秒)
#--------------超时配置----------------------
#hystrix超时
hystrix.command.default.execution.timeout.enabled=true
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=70000
#开启重试机制
spring.cloud.loadbalancer.retry.enabled=true
#当前服务器连接次数
ribbon.MaxAutoRetries=2
#下个负载均衡服务器连接次数
ribbon.MaxAutoRetriesNextServer=1
#请求处理的超时时间
ribbon.ReadTimeout=14000
#请求连接超时时间
ribbon.ConnectTimeout=10000
#--------------超时配置----------------------
执行超时:14秒,连接超时:10秒,熔断:150秒,本服务器重试次数:2次,下个服务器重试次数:1次,假如服务B执行需要200秒,
Feign是get接口,实际需要84秒超时
Feign是post接口,实际需要14秒超时
由此可以看出得出如下结论
结论一:get请求时会重试。post请求不会重试,主要是考虑到幂等性问题。当然可以通过配置强制所有接口都重试(不推荐)
由实际测试结果看,实际的超时时间并没有包括配置的连接超时时间,这一点跟官网给出的超时时间的计算是有出入的,原因未知。
get:T2 = 14*(1+2)*(1+1) = 84秒
post:T2 = 14*1*1 = 14秒
如果把熔断超时修改为70秒,其他配置不变
则实际超时时间如下
get:min(14*(1+2)*(1+1), 70)=70
Post: min(14*1*1, 70)=14
结论二:熔断的超时时间要大于执行超时
这是在服务A中看到的时间结果,但是由于zuul配置的超时时间是60秒,所以返回给用户的信息是60秒就已经超时。
二、网关的超时时间测试
FeignClient的超时时间不变,网关的超时配置如下:
#--------------超时配置----------------------
#hystrix超时
hystrix.command.default.execution.timeout.enabled=true
zuul.ribbonIsolationStrategy=THREAD
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=90000
#开启重试机制
zuul.retryable=true
#当前服务器连接次数
ribbon.MaxAutoRetries=1
#下个负载均衡服务器连接次数
ribbon.MaxAutoRetriesNextServer=1
#请求处理的超时时间
ribbon.ReadTimeout=15000
#请求连接超时时间
ribbon.ConnectTimeout=10000
#--------------超时配置----------------------
实际超时时间:
Get请求时: T1 = 15*(1+1)*(1+1) = 60秒
Post请求时: T1 = 15秒
如果把熔断的超时时间改为40秒,其他不变
#--------------超时配置----------------------
#hystrix超时
hystrix.command.default.execution.timeout.enabled=true
zuul.ribbonIsolationStrategy=THREAD
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=40000
#开启重试机制
zuul.retryable=true
#当前服务器连接次数
ribbon.MaxAutoRetries=1
#下个负载均衡服务器连接次数
ribbon.MaxAutoRetriesNextServer=1
#请求处理的超时时间
ribbon.ReadTimeout=15000
#请求连接超时时间
ribbon.ConnectTimeout=10000
#--------------超时配置----------------------
Get请求时: T1 = min(40, 15*(1+1)*(1+1)) = 40秒
Post请求时: T1 = min(40, 15) = 15秒