针对跟外部对接,使用httpclient进行请求可能会报NoHttpResponseException,原因有可能是当时target服务器负载过大,或者服务端连接空闲自动挂起,或者客户端的http请求机制跟服务端不一致(这次就是这个原因,客户端使用socket的空闲连接,服务器端是短连接)。
刚开始发现NoHttpResponseException,网上也查了一些资料,设置HttpClients的setRetryHandler,增加针对NoHttpResponseException的重试机制
setRetryHandler参考文章:https://blog.csdn.net/siantbaicn/article/details/80854528
https://blog.csdn.net/liubenlong007/article/details/78180333
发现公共方法中重试次数3改为了1,也就是没有重试机制,沟通后改成3,发布生产环境,结果发现还是有报NoHttpResponseException的数据,虽然数据量减少。继续排查
本地写一个压测的简单方法,进行接口测试,结果本地没有报NoHttpResponseException,排除服务器负载过大的情况,况且目标服务器用的f5硬负载均衡,抗负载能力应该是很强的。
因为不知道合作方提供的服务器配置情况,询问也是很久没回复,但是不能影响业务啊,那就是抓取网络包进行查看。
tcpdump 生成scp文件,然后wireshark软件进行查看。
sudo tcpdump -i eth0 -w lmstcp.cap host 1.1.0.52 and tcp port 8080 &
发现NoHttpResponseException的一个http流,发现服务器在http处理200后,向客户端发出了挥手FIN,ACK,客户端也进行ACK,但此时客户端又来了一个http请求,而且是使用了前面但TCP,服务器端直接进行了RST,丢弃掉该次链接。
经过抓包发现,服务端对http请求完后就断开了tcp,但是客户端是使用的http client连接池,共享了tcp socket的,发现socket是有30S空闲时间的,此时新的http过来时沿用了空闲中的tcp,修改为0,让采用新创建socket,继续发版本,进行数据测试。
// 可用空闲连接过期时间,重用空闲连接时会先检查是否空闲时间超过这个时间,如果超过,释放socket重新建立
connManager.setValidateAfterInactivity(0);//改为0 立即释放socket
结果还是存在NoHttpResponseException数据,继续查资料,空闲时间为0了,但是socket还是会被回收到池中的,回收池中复用策略
-
如果request首部中包含Connection:Close,不复用
-
如果response中Content-Length长度设置不正确,不复用
-
如果response首部包含Connection:Close,不复用
-
如果reponse首部包含Connection:Keep-Alive,复用
-
都没命中的情况下,如果HTTP版本高于1.0则复用
继续修改,将请求的request的Header中response.setHeader("connection", "close");强制tcp不回收到池中,相当于短链接请求。
经过这一问题排查,对网络通信更加了解,http tcp的请求等,还是需要懂原理,这样排查问题能更迅速定位原因,同时能读源码还是看源码解决问题,下面是解决问题时看到的文章。
针对keep-alive的http tcp的解释,http1.0需要手动开启,http1.1后默认开启,参考文章:
https://www.cnblogs.com/hukey/p/5481173.html
https://blog.csdn.net/weixin_37672169/article/details/80283935
针对网络通信的文章,下面的集合文章比较全了:
https://blog.csdn.net/yi_master/article/details/80579134
nginx的抓包分析文章:
https://segmentfault.com/a/1190000018011857
tcpdump,以及wireshark工具:
https://blog.csdn.net/qq_19167629/article/details/83088878
https://blog.csdn.net/qq_28699375/article/details/78860016
wireshark过滤规则,以及使用方法:
https://blog.csdn.net/wojiaopanpan/article/details/69944970
wireshark tcp seq ack说明:
https://blog.csdn.net/wang7dao/article/details/16805337
httpclient源码解析:
https://www.cnblogs.com/shoren/p/httpclient-leaseConnection.html
https://www.cnblogs.com/cherish010/p/9242756.html
http connection close:
https://www.cnblogs.com/liluxiang/p/9474907.html