Jmeter性能测试过程中遇到connection reset的解决方案
先说结果:HTTP请求中设置合理的超时时间
问题现象
在Linux服务器上使用命令行模式执行性能测试时,会遇到JMeter进程不能在预期时间内结束,导致后续所有要执行的脚本都被阻塞的问题。
查看错误日志,发现有许多connection reset:“Non HTTP response message: Connection reset”。
connection reset是什么?
要解释connection reset,就要先解释Keep-Alive长链接。
keep-alive
JMeter 中的 keep-alive 是 HTTP 协议的一个特性,允许客户端和服务器在单个 TCP 连接上发送和接收多个 HTTP 请求/响应,而不是为每个请求建立新的连接。这减少了网络开销,提高了性能。
keep-alive 的工作原理
当启用 keep-alive 时,客户端(JMeter)会在第一次请求时建立 TCP 连接,并在后续请求中复用该连接。服务器会在响应头中返回 Connection: keep-alive
,表示支持长连接。如果服务器不支持,则会返回 Connection: close
,强制关闭连接。
keep-alive 的优势
- 减少延迟:避免了重复建立 TCP 连接的三次握手过程。(通过 View Results Tree 或 Aggregate Report 监听器可以看到
Connect Time显著降低,说明
keep-alive 生效。) - 降低服务器负载:减少了频繁创建和销毁连接的开销。
- 提高吞吐量:在高并发场景下,复用连接可以显著提升性能。
keep-alive 的注意事项
- 连接超时:服务器可能会设置 keep-alive 的超时时间,闲置连接会被关闭。这时Jmeter会收到connection reset的错误。
在我们的测试过程中,这种问题在高并发时更为常见,因为在我们的脚本中使用了同步定时器,所有线程都必须等待最慢线程完成,才能进入下一轮迭代。高并发时,最快线程与最慢线程之间的响应时间可能差距更大,导致最快线程的等待时间超出服务端的超时时间,连接被关闭。这些被关闭的连接将向JMeter返回connection reset。
- 资源占用:长连接会占用服务器和客户端的资源,需合理配置。
- JMeter 行为:JMeter 默认会复用连接,但每个线程组的线程会维护独立的连接池。每个线程根据需要,会维护一个或多个长链接:
- 无并行控制器时,每个线程维护单个长连接串行复用
- 使用并行控制器时,每个线程需要维护多个独立连接(=并行请求数)
重要事项
Connection reset是操作系统内核(TCP协议栈)返回的信息,JMeter将它视为网络错误,而非服务端应用层返回的业务响应。Jmeter会继续等待业务响应。但是因为服务端已经关闭了连接,自然也无法返回业务响应。如果JMeter没有设置合理的超时时间,它就会一直等待下去,导致线程阻塞,JMeter脚本超时无法结束。(这也解释了为什么在出现Connection reset错误时,开发人员通常无法在应用系统日志中找到对应的错误,甚至会反馈说系统并未在指定时间接收到对应的请求。)
解决方案
所以,为了在出现问题时JMeter线程不被阻塞,仍然能按照预定执行时间结束,就需要为HTTP请求设置合理的超时时间。