博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HttpClient请求外部服务器NoHttpResponseException
阅读量:4041 次
发布时间:2019-05-24

本文共 1624 字,大约阅读时间需要 5 分钟。

针对跟外部对接,使用httpclient进行请求可能会报NoHttpResponseException,原因有可能是当时target服务器负载过大,或者服务端连接空闲自动挂起,或者客户端的http请求机制跟服务端不一致(这次就是这个原因,客户端使用socket的空闲连接,服务器端是短连接)。

刚开始发现NoHttpResponseException,网上也查了一些资料,设置HttpClients的setRetryHandler,增加针对NoHttpResponseException的重试机制

setRetryHandler参考文章:

                                            

发现公共方法中重试次数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后默认开启,参考文章:

针对网络通信的文章,下面的集合文章比较全了:

nginx的抓包分析文章:

tcpdump,以及wireshark工具:

wireshark过滤规则,以及使用方法:

wireshark tcp seq ack说明:

httpclient源码解析:

http connection close:

 

转载地址:http://vgadi.baihongyu.com/

你可能感兴趣的文章
Idea导入的工程看不到src等代码
查看>>
技术栈
查看>>
Jenkins中shell-script执行报错sh: line 2: npm: command not found
查看>>
8.X版本的node打包时,gulp命令报错 require.extensions.hasownproperty
查看>>
Jenkins 启动命令
查看>>
Maven项目版本继承 – 我必须指定父版本?
查看>>
Maven跳过单元测试的两种方式
查看>>
通过C++反射实现C++与任意脚本(lua、js等)的交互(二)
查看>>
利用清华镜像站解决pip超时问题
查看>>
[leetcode BY python]1两数之和
查看>>
微信小程序开发全线记录
查看>>
PTA:一元多项式的加乘运算
查看>>
CCF 分蛋糕
查看>>
解决python2.7中UnicodeEncodeError
查看>>
小谈python 输出
查看>>
Django objects.all()、objects.get()与objects.filter()之间的区别介绍
查看>>
python:如何将excel文件转化成CSV格式
查看>>
机器学习实战之决策树(一)
查看>>
机器学习实战之决策树二
查看>>
[LeetCode By Python]7 Reverse Integer
查看>>