使用httpclient时报错NoHttpResponseException failed to respond

异常信息

org.apache.http.NoHttpResponseException xxx failed to respond
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:141)
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:56)
at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:259)

其实这个异常是偶发的,就是因为偶发所以不太好查,主要是本地不好复现,只在服务器压测时有问题

上网找了些解答,但说的其实不太清楚,最后再stackoverflow找到答案了

https://stackoverflow.com/questions/10558791/apache-httpclient-interim-error-nohttpresponseexception#

解决方案其实在官方文档里也有解答 http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html

主要是这段

2.5. Connection eviction policy

One of the major shortcomings of the classic blocking I/O model is that the network socket can react to I/O events only when blocked in an I/O operation. When a connection is released back to the manager, it can be kept alive however it is unable to monitor the status of the socket and react to any I/O events. If the connection gets closed on the server side, the client side connection is unable to detect the change in the connection state (and react appropriately by closing the socket on its end).

HttpClient tries to mitigate the problem by testing whether the connection is 'stale', that is no longer valid because it was closed on the server side, prior to using the connection for executing an HTTP request. The stale connection check is not 100% reliable. The only feasible solution that does not involve a one thread per socket model for idle connections is a dedicated monitor thread used to evict connections that are considered expired due to a long period of inactivity. The monitor thread can periodically call ClientConnectionManager#closeExpiredConnections() method to close all expired connections and evict closed connections from the pool. It can also optionally call ClientConnectionManager#closeIdleConnections() method to close all connections that have been idle over a given period of time.

这个异常的原因就是客户端创建了到服务端的连接,但是服务端会在连接空闲时关闭这个连接,而HttpClient无法感知这个事件,所以继续使用这个链接就报错了,毕竟那边都断了

Most likely persistent connections that are kept alive by the connection manager become stale. That is, the target server shuts down the connection on its end without HttpClient being able to react to that event, while the connection is being idle, thus rendering the connection half-closed or 'stale'.

解决方案其实就是配置两个参数,使用httpclient的话基本都会用到线程池

PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.closeExpiredConnections();
//这里的空闲时间要和keepalive配合使用,比如keepalive配置20s,那这里的关闭空闲时间最好配置15s
        connectionManager.closeIdleConnections(closeIdleTime, TimeUnit.SECONDS);
connectionManager.closeExpiredConnections();  关闭过期链接
connectionManager.closeIdleConnections(closeIdleTime, TimeUnit.SECONDS);  隔多久关闭空闲状态的链接

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值