记一次NoHttpResponseException:xxx failed to respond

2 篇文章 0 订阅
2 篇文章 0 订阅

1. 为什么会发生这个异常

        首先了解 KeepAlive:HTTP的连接复用机制,在HTTP1.0时代,每个请求经过三次握手后,只会传输一次HTTP请求和响应报文后,就进入四次挥手关闭连接了。而TCP建立连接和关闭连接的代价是比较大的,导致HTTP1.0的通道利用率较低,时延较高。针对这个问题,推出Keepalive机制,一个TCP连接建立后,可以在上面发送多个HTTP报文,只有这个TCP连接的空闲时间达到超时时间,才会被关闭

        异常原因:服务端闲置时间超过配置的Keepalive,会主动断开TCP链接,然后客户端使用半断开的链接发起请求时,服务端响应RST包导致此异常情况的发生

2. 实际项目中遇到的案例

注:想要了解kettle相关的见这篇文章https://mp.csdn.net/mp_blog/creation/editor/126256536

kettlepack配置定时任务,底层通过Http请求定时调度远程Carte服务,调度kettle的作业/转换任务,即类似于客户端A -> 调用服务端B,然后就出现了这个异常,如图

 3. 深入源码分析问题

        ① 确认服务端的空闲超时时间:案例中服务端指的是kettle的远程carte服务,通过本地模拟Http请求调用carte服务,抓包看出运行服务的web容器是内嵌的Jetty。所以需要看Jetty配置的KeepAlive,源码分析如下:

  1. Connector接受远程机器的连接和数据,允许应用向远程机器发送数据
  2. 它有个子类AbstractConnector继承ContainerLifeCycle,所以具有Container和LifeCycle特性
  3.  此外有一个ServerConnector,这个是整个Jetty中很重要的连接器,目前该连接器负责HTTP和HTTPS协议等连接
  4.  ConnectionFactory负责为连接器创建连接对象,不同的连接(HTTP)创建不同的连接对象

② 确认客户端的空闲超时时间:跟踪kettlepack源码,得知底层通过本地调用kettle源码,跟踪到源码位置:

 

 

最后定位到客户端发起的Http请求配置的keepAlive= -1,即闲置永不关闭。

  4. 总结

        上述案例,服务端配置的闲置超时时间=3000,所以在某种情况超过这个闲置时间,服务端会主动关闭TCP连接,但是客户端依然在复用这个连接,就会导致这个异常。

结合该案例如何解决:

        在我找到原因之后,由于我们公司使用的是kettle开源工具,没有定制它的源码,所以我们在项目中只是将服务端的超时时间适当的配大了一点,尽量减少异常的次数

这里推荐几个其它方案,了解原因,最终怎么解决结合具体的业务场景:

① http请求使用重发机制,捕获NohttpResponseException的异常,重新发送请求,重发3次后还是失败才停止

② 客户端配置的空闲时间小于服务端的空闲时间,可以完全规避这个异常(该方案最优)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值