JMeter单线程POST请求运行30-45分钟报ConnectionClosedException如何解决
错误根因说明
该异常本质是服务端返回Transfer-Encoding: chunked分块编码格式的响应时,还未传输完分块结束标记就提前断开了TCP连接,触发原因是开启Keep-Alive长连接后,JMeter的连接存活时间配置大于服务端的长连接超时阈值,服务端会主动回收空闲的长连接,刚好回收发生在请求响应传输的过程中,就会抛出该错误。
可落地的解决方案
方案1:调整JMeter全局长连接存活配置
找到JMeter安装目录下bin文件夹中的jmeter.properties文件,修改如下参数:# 单位为毫秒,设置为比服务端长连接超时时间短1-2分钟即可,比如服务端默认30分钟超时就设置为1740000(29分钟) httpclient4.time_to_live=1740000配置后重启JMeter生效,该配置会让JMeter在连接达到指定时长后主动销毁旧连接,使用新连接发起请求,避免被服务端主动断连。
方案2:切换HTTP请求实现方式
打开报错的HTTP请求采样器的「高级」标签页,将「HTTP请求实现」从默认的HttpClient4切换为Java,Java实现的连接容错处理逻辑对这类服务端提前断连的场景兼容性更强,多数情况下可以直接规避该报错。方案3:关闭Keep-Alive选项
当前是单线程执行任务,若对请求性能没有极高要求,直接取消HTTP请求采样器的「使用Keep-Alive」勾选即可,每次请求都会新建独立连接,完全避免长连接被服务端回收导致的断连问题。方案4:添加请求重试机制
在jmeter.properties文件中修改重试参数,配置连接异常自动重试:# 配置最多重试3次 httpclient4.retrycount=3 # 重试时允许非幂等的POST请求重试 httpclient4.request_sent_retry_enabled=true遇到该类断连异常时JMeter会自动发起重试,重试会使用新连接,可保障请求成功率。
方案5:调整服务端长连接配置
若有权限修改被调用API的服务端配置,可将服务端的长连接超时阈值调大至大于单次任务的总运行时长,比如Nginx就调整keepalive_timeout参数为1h,避免服务端中途主动断开JMeter的长连接。
完整异常栈信息
org.apache.http.ConnectionClosedException: Premature end of chunk coded message body: closing chunk expected at org.apache.http.impl.io.ChunkedInputStream.getChunkSize(ChunkedInputStream.java:263) at org.apache.http.impl.io.ChunkedInputStream.nextChunk(ChunkedInputStream.java:222) at org.apache.http.impl.io.ChunkedInputStream.read(ChunkedInputStream.java:183) at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:135) at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:148) at org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase.readResponse(HTTPSamplerBase.java:1936) at org.apache.jmeter.protocol.http.sampler.HTTPAbstractImpl.readResponse(HTTPAbstractImpl.java:476) at org.apache.jmeter.protocol.http.sampler.HTTPHC4Impl.sample(HTTPHC4Impl.java:673) at org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy.sample(HTTPSamplerProxy.java:66) at org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase.sample(HTTPSamplerBase.java:1296) at org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase.sample(HTTPSamplerBase.java:1285) at org.apache.jmeter.threads.JMeterThread.doSampling(JMeterThread.java:638) at org.apache.jmeter.threads.JMeterThread.executeSamplePackage(JMeterThread.java:558) at org.apache.jmeter.threads.JMeterThread.processSampler(JMeterThread.java:489) at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:256) at java.lang.Thread.run(Unknown Source)
内容的提问来源于stack exchange,提问作者Ganesh Pethkar

