jMeter解决failed to respond Connection reset

jMeter测试单个接口测试都没有问题,多个接口依次测试,就会有部分The target server failed to respond,有的会返回Connection reset。我们一步步来看看怎样解决

  1. 1
    解决办法

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

    ----

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

    ----

    去掉勾选Use KeepAlive

    连接就不会复用,这样也就不存在空闲超时,被服务端干掉的情况了。

    但带来的是性能的开销,因为tcp每次都要关闭然后重建。

    jMeter解决failed to respond Connection reset
  2. 2

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

    jMeter解决failed to respond Connection reset
  3. 3

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

    ----

    把 connectionTimeout 尽可能的调大,

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

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

    ----

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

    END
  1. 1
    接口测试总结

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

    (以2000并发为例)

    ----

    1:ideltimeout不配置,只配置connectionTimeout==20s

    ----

    一批接口中

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

    ----

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

    ----

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

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

    ----

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

    ----

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

  2. 2

    2:ideltimeout < connectionTimeout的情况

    ----

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

    ----

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

    ----

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

    ----

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

    ----

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

  3. 3

    3:当Ideltimeout > connectionTimeout时:

    ----

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

    ----

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

  4. 4

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

    1:ideltimeout不配置,只配置connectionTimeout

    2:Ideltimeout > connectionTimeout

    3:ideltimeout <= connectionTimeout

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

    这是jMeter中ideltimeout的配置:

    ----

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

    jMeter解决failed to respond Connection reset
  2. 2

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

    jMeter解决failed to respond Connection reset
  3. 3

    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注释了下的情况)

    jMeter解决failed to respond Connection reset
  4. 4

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

    ----

    这是jMeter中返回的结果:

    jMeter解决failed to respond Connection reset
  5. 5

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

    ideltimeout == 10s时:

    ----

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

    这都超了33秒了,早就超过ideltimeout==10s的配置了

    ----

    但这个配置还是还是管用的,不然也不会有(70行)的主动关闭连接。

    jMeter解决failed to respond Connection reset
  6. 6

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

    ----

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

    jMeter解决failed to respond Connection reset
  7. 7

    那么我们就知道:

    jMeter有两种主动关闭连接的方式

    ----

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

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

    END
  1. 1
    找到造成failed to respond的原因

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

    默认的tcp_keepalive_time是7200;

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

    jMeter解决failed to respond Connection reset
    jMeter解决failed to respond Connection reset
  2. 2

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

    ----

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

    访问 /api/vi/home

    ----

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

    ----

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

    jMeter解决failed to respond Connection reset
  3. 3

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

    ----

    从下图可以看到 

    第一次请求/api/vi/home 经过了三次握手

    紧接着请求/api/v1/home/seckill?sec=2 就直接传数据了

    这是复用了tcp连接。

    jMeter解决failed to respond Connection reset
  4. 4

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

    ----

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

    ----

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

    jMeter解决failed to respond Connection reset
  5. 5

    但在jMeter中,如果20s超时,服务端发来FIN+ACK,客户端回一个ACK,但客户端并不会再回一个FIN+ACK,也就是说不理会服务端的主动关闭

    ----

    这时服务端的tcp连接的状态是FIN_WAIT2, 客户端的tcp连接的状态是CLOSE_WAIT。

    这也就是为什么服务端有很多FIN_WAIT2的原因!

    jMeter解决failed to respond Connection reset
  6. 6

    到下一个接口测试的时候,复用了这个连接,服务端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

    jMeter解决failed to respond Connection reset
    END