jMeter: The target server failed to respond Connection reset

赞赏 2016-08-17

jMeter测试单个接口测试都没有问题,多个接口依次测试,就会有部分The target server failed to respond 和 java.net.SocketException: Connection reset,下面就看看如何解决这种错误。
篇幅较长,测试环节较多,耐心阅读!

jMeter: The target server failed to respond Connection reset

1 找到造成failed to respond的原因

先看一下服务端的相关配置: 

默认的tcp_keepalive_time是7200 

tomcat的server.xml的配置 connectionTimeout是20s


从抓包查看浏览器中一个正常访问的开始 

客户端ip:192.168.1.101,服务端ip: 192.168.1.50 

访问 /api/vi/home 


从下图wireshark的抓包数据,可以看到22行,客户端回了一个ACK,这次请求的数据已经传出完毕了,服务端连接的状态是 ESTABLISHED。 

20s后,服务端发了一个FIN+ACK,主动关闭这个连接(因为tomcat中设置了20s超时), 四次挥手这个连接就关闭了。



如果 /api/vi/home 这个访问响应完后的20s内,有新的请求产生,就会复用这个tcp连接,就不用在3次握手了。 

从下图可以看到 第一次请求/api/vi/home 经过了三次握手

紧接着请求/api/v1/home/seckill?sec=2 就直接传数据了, 这时复用了tcp连接。


如果超过了20s,连接被服务端主动关闭了,浏览器中再次请求的时候,就会建立一条新的连接。

这也就是HttpClient的连接池机制,可以复用tcp连接,这样能有效减少服务端开销和缩短响应时间。 

在浏览器中访问,服务端主动去关闭的时候,客户端也就跟着关闭了,四次挥手!


但在jMeter中,如果20s超时,服务端发来FIN+ACK,客户端回一个ACK,但客户端并不会再回一个FIN+ACK,也就是说不理会服务端的主动关闭 这时服务端的tcp连接的状态是FIN_WAIT2, 客户端的tcp连接的状态是CLOSE_WAIT。 这也就是为什么服务端有很多FIN_WAIT2的原因!



到下一个接口测试的时候,复用了这个连接,服务端tcp就会返回RST,而http就是空应答,HttpClient在解析HTTP头时,发现没有数据,因为没有返回HTTP数据包,而是返回了TCP数据包。

就会在jMeter中看到如下错误: Response code: Non HTTP response code: org.apache.http.NoHttpResponseException Response message: Non HTTP response message: The target server failed to respond



2 复现空闲超时被服务端主动关闭的情况

这是jMeter中ideltimeout的配置: 

bin/jmeter.properties 这个文件中,有关于ideltimeout的配置,目前是注释的。


我们测试线程数是2,两个接口(seckill接口,home接口),循环次数1。 

seckill接口的地址:/api/v1/home/seckill?sec=${sec} 

home接口的地址: /api/v1/home 


在seckill接口中 

/api/v1/home/seckill?sec=1的时候 sleep了30s 

/api/v1/home/seckill?sec=2的时候,正常处理 

这样就能保证,/api/v1/home/seckill?sec=2的这条连接等到测试home接口的时候,已经超过了20s,被服务端主动关闭了


看抓包结果: 

(ideltimeout注释了的情况) 

可以看到: 端口57513(/api/v1/home/seckill?sec=2),在空闲20后(51行)的时候,被服务端主动关闭,等到下一个接口/api/v1/home要用的时候,服务端返回RST(63行)


这是jMeter中返回的结果:


我们开启ideltimeout,看看这个timeout好不好使 

ideltimeout == 10s时:  

可以看到20s后(53行)被服务端主动关闭,/api/v1/home/seckill这个接口并发完成后(69行是都完成了),才在(70行)主动去关闭端口为57590的这个超时连接。

这都超了33秒了,早就超过ideltimeout==10s的设置了 但这个设置还是还是管用的,不然也不会有(70行)的主动关闭连接。


我们再看看ideltimeout == 20s的时候: 


可以看到无论是20s 还是10s,连接都不是实时释放的,都是等这个接口测试完,才去释放的,也就是说,这个ideltimeout 是等一个接口测试完,然后再去查看每个连接的空闲时间,如果有的超过了ideltimeout,就主动关闭它。


那么我们就知道: jMeter有两种主动关闭连接的方式

1:一个接口并发完,空闲时间超过 ideltimeout 的线程,干掉 

2:全部测试完成,主动关闭所有连接。



3 接口测试总结

通过以上可总结三种情况错误的情况如下:

(以2000并发为例,一批接口的第一轮测试) 


1)ideltimeout不设置,只设置connectionTimeout==20s 

第一个接口肯定不会出现,因为他都是新建的tcp连接。

第二个接口容易出现RST,因为第一个接口新建连接比较耗时,容易造成测到第二个接口的时候,一些连接已经超过了20s,被服务端主动关闭了。

耗时的接口上,容易出现RST 

比如接口4,复用接口3的2000连接(我们以1~2000标记),说是并发执行,其实在服务端也是个队列,假设到复用1900以后的了连接了,1900以前已经耗时了20s, 这1900以后的连接其实已经被服务端主动关闭了。(有些连接在接口3中已经空闲了一段时间,到接口4都不用20s就被关闭了 )。

耗时的接口的下一个接口,容易出现RST,原因耗时接口到下一个接口的时候,有些空闲的时间比较长。


所以如果不设置ideltimeout,很容易造成累计效应,越到最后,可能出错的几率越高


2)ideltimeout < connectionTimeout的情况 

设置 ideltimeout == 10s,设置connectionTimeout==20s 

第一个接口肯定不会出现,同上 

第二个接口出错的几率比第一种情况就小很多,因为到第二个接口的时候没有连接 的空闲时间是超过了10s的,只有连接复用的时候如果空闲超过了20s,被服务端主动关闭的连接才会出错。 

耗时的接口上,容易出现RST,但比第一种情况几率小一些。 

耗时的接口的下一个接口,比第一种情况几率也小一些。


3)当Ideltimeout > connectionTimeout时: 

设置 ideltimeout == 60s,设置connectionTimeout==20s 

他比第一种情况好,比第二种情况差。 

所以出错的几率大概是这样的:(由大到小) 

1:ideltimeout不设置,只设置connectionTimeout 

2:Ideltimeout > connectionTimeout 

3:ideltimeout <= connectionTimeout



4 解决办法

正常的客户端访问,不会出现这样的情况,因为正常通信的情况下,服务端主动关闭,客户端连接也会释放掉。 

但是jMeter中,服务端主动关闭,他根本就不理会。那么有没有jMeter中实时主动关闭的办法那?  

有 

去掉勾选Use KeepAlive 连接就不会复用,这样也就不存在空闲超时,被服务端干掉的情况了。 但带来的是性能的开销,因为tcp每次都要关闭然后重建。


可是,正常浏览器访问请求头中也是带Connection:keep-alive的,所以去掉的话,测试出的吞吐量就不太合理。


那这个问题就落在服务端的主动关闭上了,不让服务端主动关闭就行了。 

把 connectionTimeout 尽可能的调大

建议 connectionTimeout = 最耗时接口的一次并发的总时间 * 接口个数 

Ideltimeout <= 最耗时接口的一次并发的总时间 

测试完,把connectionTimeout这个值在改回原值即可。



5 java.net.SocketException: Connection reset

还有如下错误


通过抓包 发现 其实是通信异常了

java.net.SocketException如何才能更好的使用呢?

这个就需要我们先要了解有关这个语言的相关问题。希望大家有所帮助。那么我们就来看看有关java.net.SocketException的相关知识。




6 java.net.SocketException五大异常解决方案


第1个异常是 

java.net.BindException:Address already in use: JVM_Bind。 


该异常发生在服务器端进行new ServerSocket(port)(port是一个0,65536的整型值)操作时。异常的原因是以为与port一样的一个端口已经被启动,并进行监听。 此时用netstat –an命令,可以看到一个Listending状态的端口。只需要找一个没有被占用的端口就能解决这个问题。


第2个异常是

java.net.SocketException: Connection refused: connect。 


该异常发生在客户端进行 new Socket(ip, port)操作时,该异常发生的原因是或者具有ip地址的机器不能找到(也就是说从当前机器不存在到指定ip路由),或者是该ip存在,但找不到指定的端口进行监听。 出现该问题,首先检查客户端的ip和port是否写错了,如果正确则从客户端ping一下服务器看是否能ping通,如果能ping通(服务服务器端把ping禁掉则需要另外的办法),则看在服务器端的监听指定端口的程序是否启动,这个肯定能解决这个问题。


第3个异常是

java.net.SocketException: Socket is closed


该异常在客户端和服务器均可能发生。异常的原因是己方主动关闭了连接后(调用了Socket的close方法)再对网络连接进行读写操作。


第4个异常是

java.net.SocketException: (Connection reset或者Connect reset by peer:Socket write error)。 


该异常在客户端和服务器端均有可能发生,引起该异常的原因有两个,第一个就是如果一端的Socket被关闭(或主动关闭或者因为异常退出而引起的关闭),另一端仍发送数据,发送的第一个数据包引发该异常(Connect reset by peer)。另一个是一端退出,但退出时并未关闭该连接,另一端如果在从连接中读数据则抛出该异常(Connection reset)。简单的说就是在连接断开后的读和写操作引起的。


第5个异常是

java.net.SocketException: Broken pipe。  


该异常在客户端和服务器均有可能发生。在第4个异常的第一种情况中(也就是抛出 SocketExcepton:Connect reset by peer:Socket write error后),如果再继续写数据则抛出该异常。前两个异常的解决方法是首先确保程序退出前关闭所有的网络连接,其次是要检测对方的关闭连接操作,发现对方关闭连接后自己也要关闭该连接。

登陆后阅读全文
阅读 5442 赞赏 6 有用 44 没用 10 收藏 6 分享

   


作者声明:本篇文章系本人原创,欢迎分享,但未经许可,谢绝转载。

0 条留言

琅琊阁主的头像

琅琊阁主

抛砖引玉

有料推荐

这世界欠我一个这样的老公!

高校学生模仿“世界名画”摆拍,可以说是戏精本精了

iPhone X 跌破发行价,苏宁200亿入股恒大 | 财经日日评

果然是高手!这次在日本,特朗普竹杠敲得不是一般狠

资深黄牛现身说法:iPhone X价格秒变不停,就像炒股一样

长一样的双胞胎也能识别?蚂蚁金服发布「眼纹识别」技术

苏联是怎么被阿富汗拖垮的?

美团或入局「分时租赁」共享汽车,王兴要大笔投入「泛出行」领域了? | 36氪独家

你或许被“一盘番茄炒蛋”刷屏了,但有人辛酸,有人质疑

iPhone X发售前夜,黄牛与苹果公司的不安

他的文章

词条 | 影子银行 | 什么是影子银行

如何保存征集助手投票助手里收集到的图片视频?

解决微信开发者工具不能复制

福利 | Purnhub的视频如何下载?

Instagram的图片和视频如何下载?

公号素材助手只下载了一张图片

提取图片中的文字 | ocr文字识别助手

Axure RP 8 注册码(最新亲测可用) Licensee + Key

福利 | 第九工厂「艺术二维码」的价值180元的三个月会员邀请码

如何9.85折给中国联通手机、固话、宽带充值?

手机扫一扫
分享文章