Feign + Ribbon + hystrix 设置超时时间,解决接口调用Socket read time out

本文讲述了作者在Spring Cloud架构中遇到的SocketTimeoutException,通过排查发现Feign的readTimeout配置未生效,深入源码分析后,通过自定义配置类解决了超时问题。关键在于理解Feign的底层实现和超时设置原理。
摘要由CSDN通过智能技术生成

首先下面这个就是万恶之源Time out

`java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:170)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:137)
at org.apache.http.impl.io.SessionInputBufferImpl.fillBuffer(SessionInputBufferImpl.java:153)
at org.apache.http.impl.io.SessionInputBufferImpl.readLine(SessionInputBufferImpl.java:280)
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:138)

首先要知道的是这个报错是发生在我使用Fein调用另一个服务的时候,由于服务端执行时间比较久导致服务之间的socket链接断开了,而且观察到断开的时候每次都是60000ms左右,所以可以猜测的是 肯定有某个地方设置了这个60秒。

判断是客户端的配置还是服务端的配置

接下来就要分析是客户端的配置还是服务端的,所以我使用postman模拟接口调用重新请求了服务端,发现即使超过了60秒也不会自动断开,那么可以肯定的就是这个配置在客户端了

客户端配置请求超时时间

我的架构是springcloud一套,也就是用了feign ,hystrix ,ribbon,所以在网上搜到了关于feign 和ribbon 的超时设置:

feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 3000
  ribbon:
	  OkToRetryOnAllOperations: false #对所有操作请求都进行重试,默认false
	  ReadTimeout: 5000   #负载均衡超时时间,默认值5000
	  ConnectTimeout: 3000 #ribbon请求连接的超时时间,默认值2000
	  MaxAutoRetries: 0     #对当前实例的重试次数,默认0
	  MaxAutoRetriesNextServer: 1 #对切换实例的重试次数,默认1
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 600000
          strategy: THREAD

在这里需要知道的两个超时的概念一个是readtimeout,一个connecttimeout, connecttimeout 是指客户端在请求连接服务端的时候的一个超时时间,readtimeout是指连接成功之后等待服务端response的时间,或者是指与服务端进行数据传输的时间。那么针对我的报错那一定就是修改readtimeout了,愁情稍微延长应该可以解决问题。hystrix的 timeout是指整个接口调用的最外层的超时时间,所以需要大于ribbon的重试时间总和。
在了解到这些属性之后我以为就这样结束了。。。
结果并没有,当我尝试接口调用的时候发现无论我怎么设置ribbon和feign的超时时间都不会生效,仍然还是60秒超时结束。一度让我怀疑这个socket read time out 可能和feign的设置没关系,网上再找发现还有人设置mvc的请求超时时间

spring:
	mvc:
      async:
        request-timeout: 300000

还有尝试设置tomcat的连接超时时间。。。。
各种能设置的都找遍以后还是不生效,最后只能老实debug看源码了…

HttpClientFeignLoadBalancedConfiguration feign整合httpclient启动配置类

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
一个比较核心的配置,顺腾摸瓜找到LoadBalancerFeignClient类里面的execute,是当我们调用feign接口时回来调用的一个方法,这个方法里面两个参数,第二参数就是关于超时的配置
在这里插入图片描述
在这里插入图片描述
在excute方法的64行会去拿这个配置的value与默认值作比较
在这里插入图片描述
再点开这个默认值 惊奇的发现 就是这个60秒,这个时间其实时feign接口调用的一个默认超时时间,如果有配置的话就会使用配置,但是我都配置了 在debug的时候发现传参过来的还是默认值!!
在这里插入图片描述
所以现在的问题最终就变成了 只要找出为什么没有正常的将配置传参过来就解决了。
feign接口调用底层时默认使用了ribbon的,所以在继续往上debug我找到了这个类:FeignRibbonClientAutoConfiguration
在这里插入图片描述
这个类看名字知道是feign调用时的负载均衡的一个配置类,昂我有意外收获的是 在最下面,有一个对Options的Bean的注入,也就是说上面这个默认的超时时间也就是在这里开始注入的,并且还有@ConditionalOnMissingBean 这个注解
在这里插入图片描述
所以我直接新建了一个config类重新注入Options 的Bean
在这里插入图片描述
最后,重启,测试,调用 ,3秒time out ,生效了!!!

所以,其实最终Socket time out 这个接口调用时的异常 实际上还是因为feign 接口调用的客户端设置的readtimeout属性来控制的,虽然我使用重新注入的方式解决了问题,但是yml配置ribbon不生效的问题 我还需要继续分析,也算有一些收获,就在次记录一下这个问题把。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一名软件修理工

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值