#参考官方配置 https://docs.spring.io/spring-cloud-openfeign/docs/2.2.5.RELEASE/reference/html/
feign:
client:
config:
default:
connectTimeout: 1000
readTimeout: 5000
hystrix:
enabled: true
#在feign和hystrix共存时,hystrix可以配置自身降级时间,默认1s
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 10000 # 设置hystrix的超时时间为6000ms
circuitBreaker:
#在当10秒的时间内,最近20次调用请求,请求错误率超过60%,则触发熔断5秒,期间快速失败,以下都是默认值
requestVolumeThreshold: 20
errorThresholdPercentage: 50
sleepWindowInMilliseconds: 5000
#设置统计的时间窗口值的毫秒值,circuit break 的打开会根据1个rolling window的统计来计算。
#若rolling window被设为10000毫秒,则rolling window会被分成n个buckets,
#每个bucket包含success,failure,timeout,rejection的次数的统计信息。默认10000。
metrics:
rollingStats:
timeInMilliseconds: 10000
feign
-
ConnectTimeout
指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间。
在java中,网络状况正常的情况下,例如使用HttpClient或者HttpURLConnetion连接时设置参数connectTimeout=5000即5秒,如果连接用时超过5秒就是抛出java.net.SocketException: connetct time out的异常 -
ReadTimeout
指的是建立连接后从服务器读取到可用资源所用的时间。
在这里我们可以这样理解ReadTimeout:正常情况下,当我们发出请求时可以收到请求的结果,也就是页面上展示的内容,但是当网络状况很差的时候,就会出现页面上无法展示出内容的情况。另外当我们使用爬虫或者其他全自动的程序时,无法判断当前的网络状况是否良好,此时就有了ReadTimeout的用武之地了,通过设置ReadTimeout参数,例:ReadTimeout=5000,超过5秒没有读取到内容时,就认为此次读取不到内容并抛出Java.net.SocketException: read time out的异常。
根据上面关于ConnectTimeout和ReadTimeout的描述,在我们使用需要设置这两项参数的服务或程序时,应该对两项参数一起设置。
一般而言两项参数的数值可以设置成一样的,可以适当把ReadTimeout设置的长一点,ConnectTimeout可以相对比较短,这是源于我们的网络状况一般较为稳定,连接时很少出现问题,但是读取时因为数据下载时的网络波动,出状况的可能性更大一些。
测试,
1. 双边连接良好
① 只设置hystrix(5s),feign的ReadTimeout、ConnectTimeout均不设置,服务方sleep1/2/3秒,结果都如下:
调用方显示了Read timed out,触发了降级,并且有进行了重试,重试了1次,间隔1秒。
############################# 第一次
1635755154447 --port : 7000 --- testHystrixSleep : 3
1635755155207 --port : 7000 --- testHystrixSleep : 3
############################# 第二次
1635755167963 --port : 7000 --- testHystrixSleep : 3
1635755168972 --port : 7000 --- testHystrixSleep : 3
由此可得 feign 的 readTimeout 默认是1s。
② 设置hystrix(5s),feign的ReadTimeout为2s,connectTimeout不设置:
服务方sleep 1s,正常返回,
服务方sleep 2s,降级,没有重试。
由此可得,在连接正常的情况下,有设置readTimeout且少于请求时间,降级只取决于readTimeout的时间。
③ 设置hystrix(5s),feign的connectTimeout为1/2s,ReadTimeout不设置:
服务方sleep 2s,无论connectTimeout是1s 还是 2s,均返回正常结果,没有重试。
由此可得,在连接正常的情况下,readTimeout的默认时间(1s)是不起效的,只取决于hystrix的时间。
④ 设置hystrix(5s),feign的connectTimeout(1s),ReadTimeout(2s)
服务方sleep 2s,直接降级,没有重试
⑤ 设置hystrix(3s),feign的connectTimeout(1s),ReadTimeout(4s)
服务方sleep 3s,直接降级,没有重试
服务方sleep 2s,正常返回
由此可得,在连接正常的情况下,hystrix、readTimeout的值取决于最小那个。
2. 停掉了服务方
①. 只设置hystrix(10s),feign的ReadTimeout、ConnectTimeout均不设置,结果都如下
:
2021-11-01 18:12:57.906 DEBUG 20248 --- [trix-provider-1] c.orion.service.TestFeignHystrixService : [TestFeignHystrixService#providerHystrix] ---> GET http://provider/providerHystrix HTTP/1.1
2021-11-01 18:12:57.906 DEBUG 20248 --- [trix-provider-1] c.orion.service.TestFeignHystrixService : [TestFeignHystrixService#providerHystrix] ---> END HTTP (0-byte body)
由此可得一下就没了。
②只设置hystrix(10s),feign的ReadTimeout(4s)、ConnectTimeout(2s)均设置,ConnectTimeout,结果都如下
2021-11-01 18:09:37.516 DEBUG 7852 --- [trix-provider-2] c.orion.service.TestFeignHystrixService : [TestFeignHystrixService#providerHystrix] ---> GET http://provider/providerHystrix HTTP/1.1
2021-11-01 18:09:37.517 DEBUG 7852 --- [trix-provider-2] c.orion.service.TestFeignHystrixService : [TestFeignHystrixService#providerHystrix] ---> END HTTP (0-byte body)
2021-11-01 18:09:39.537 DEBUG 7852 --- [trix-provider-2] c.orion.service.TestFeignHystrixService : [TestFeignHystrixService#providerHystrix] <--- ERROR SocketTimeoutException: connect timed out (2018ms)
由此可得还是取决 feign配置 的connectTimeout。
总结:
综上可得,其实在正常连接情况,都把connectTimeout配置比readTimeout小的,hystrix默认是1秒,而readTimeout也是1秒,但有时业务处理是不止1s的,所以最好配置1s以上(不用默认值),在配置hystrix的同时,也要配置好connectTimeout和readTimeout,而且上述测试可知,在readTimeout和hystrix同时在的情况下,谁小就谁决定降级时间,所以一般就把它们设置一样就好了。
----------------------------------- 分割线 -----------------------------------------
Hystrix的 局部降级 和 全局降级
首先看下,在上诉的例子里,得到的降级日志是怎么样的,我们能得到什么信息,为我们后续的局部、全局的hystrix的配置提供有效信息。
服务方会sleep 4s
,而调用方的配置如下:
feign:
hystrix:
enabled: true
okhttp:
enabled: true
client:
config:
default:
connectTimeout: 2000
readTimeout: 10000
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000 # 设置hystrix的超时时间,默认1s
2021-11-01 18:51:54.933 DEBUG 12268 --- [trix-provider-6] c.orion.service.TestFeignHystrixService : [TestFeignHystrixService#providerHystrix] ---> GET http://provider/providerHystrix HTTP/1.1
2021-11-01 18:51:54.933 DEBUG 12268 --- [trix-provider-6] c.orion.service.TestFeignHystrixService : [TestFeignHystrixService#providerHystrix] ---> END HTTP (0-byte body)
2021-11-01 18:51:57.942 DEBUG 12268 --- [trix-provider-6] c.orion.service.TestFeignHystrixService : [TestFeignHystrixService#providerHystrix] <--- ERROR SocketTimeoutException: Read timed out (3008ms)
2021-11-01 18:51:57.944 DEBUG 12268 --- [trix-provider-6] c.orion.service.TestFeignHystrixService : [TestFeignHystrixService#providerHystrix] java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
略...
2021-11-01 18:51:57.955 DEBUG 12268 --- [trix-provider-6] c.orion.service.TestFeignHystrixService : [TestFeignHystrixService#providerHystrix] <--- END ERROR
我们得到了 TestFeignHystrixService#providerHystrix
, 这是一个hystrixCommandKey,而hystrix配置的格式是这样的:hystrix.command.<HystrixCommandKey>.execution.isolation.thread.timeoutInMilliseconds: 100 ,默认是default即全局,而如果我们需要自定义某个方法,即自定义hystrixCommonKey,由日志得出,很显然HystrixCommandKey就是@feignClient描述的接口类以及调用方法(带参数类型)
组成的。
所以进行以下配置测试:(附带上了circuitBreaker)
feign:
hystrix:
enabled: true
okhttp:
enabled: true
client:
config:
default:
connectTimeout: 2000
readTimeout: 10000
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000 # 设置hystrix的超时时间,默认1s
circuitBreaker:
#在当10秒的时间内,最近20次调用请求,请求错误率超过60%,则触发熔断5秒,期间快速失败,以下都是默认值
requestVolumeThreshold: 20
errorThresholdPercentage: 50
sleepWindowInMilliseconds: 5000
#设置统计的时间窗口值的毫秒值,circuit break 的打开会根据1个rolling window的统计来计算。
#若rolling window被设为10000毫秒,则rolling window会被分成n个buckets,
#每个bucket包含success,failure,timeout,rejection的次数的统计信息。默认10000。
metrics:
rollingStats:
timeInMilliseconds: 10000
TestFeignHystrixService#providerPartHystrix(Integer):
execution:
isolation:
thread:
timeoutInMilliseconds: 5000 # 设置hystrix的超时时间,默认1s
circuitBreaker:
#在当10秒的时间内,最近20次调用请求,请求错误率超过60%,则触发熔断5秒,期间快速失败,以下都是默认值
requestVolumeThreshold: 20
errorThresholdPercentage: 50
sleepWindowInMilliseconds: 5000
#设置统计的时间窗口值的毫秒值,circuit break 的打开会根据1个rolling window的统计来计算。
#若rolling window被设为10000毫秒,则rolling window会被分成n个buckets,
#每个bucket包含success,failure,timeout,rejection的次数的统计信息。默认10000。
metrics:
rollingStats:
timeInMilliseconds: 10000
提供了一个providerPartHystrix(Integer a) 方法:
@Service
@FeignClient(value = "provider", fallback = TestFeignHystrixServiceFallback.class)
public interface TestFeignHystrixService {
@GetMapping("/providerHystrix") //hystrix降级配置3秒 ,服务方sleep 4秒
Result providerHystrix();
@GetMapping("/providerPartHystrix") //hystrix降级配置5秒 ,服务方sleep 4秒
Result providerPartHystrix(@RequestParam("a") Integer a);
}
在进行请求后,http://127.0.0.1:8000/hystrix/providerPartHystrix,正常返回结果:
{"msg":"Success","code":1000,"data":"port : 7000 --- testPartHystrixSleep : 4 -- a : 1"}
网友评论