性能测试中长连接(keep-alive)响应时间高于短连接的原因及优化方案
性能测试中长连接平均响应时间高于短连接的原因及优化方案
问题
为何在性能测试中长连接(keep-alive)的整体平均响应时间会超过短连接(close)?该现象的原因是什么,又该如何优化?
测试结果
- 平均响应时间:14.01ms > 9.76ms(keepalive 模式 > close 模式)
测试命令
- POST 500KB数据,keepalive模式:
wrk -t8 -c16 -d1m -s post.lua --latency --timeout 5s http://10.129.9.39:5074/user
- POST 500KB数据,close模式:
wrk -t8 -c16 -d1m -s post_close.lua --latency --timeout 5s http://10.129.9.39:5074/user
说明:客户端POST 500KB数据,服务器返回字符串"ok"。
测试脚本内容
post.lua(keepalive模式)
wrk.method = "POST" wrk.headers["Content-Type"] = "application/json" wrk.headers["Connection"] = "keep-alive" local file = io.open("/root/tls/500kb.json", "rb") wrk.body = file:read("*all") file:close()
post_close.lua(close模式)
wrk.method = "POST" wrk.headers["Content-Type"] = "application/json" wrk.headers["Connection"] = "close" local file = io.open("/root/tls/500kb.json", "rb") wrk.body = file:read("*all") file:close()
现象原因分析
- 连接复用的串行阻塞:HTTP/1.1的长连接默认串行处理请求,同一连接上的请求必须等待前一个完成才能开始处理。若某一次请求出现延迟,后续复用该连接的请求都会被阻塞,直接拉高整体平均响应时间。而短连接每次请求独立新建,请求间互不影响,不会出现连锁阻塞。
- 服务器连接池配置不当:如果长连接空闲超时设置过短,会导致连接频繁销毁重建,产生额外开销;若连接池容量不足,新请求无法获取可用连接只能等待;闲置连接未及时清理,存在资源泄漏或状态异常,也会影响处理效率。
- TCP拥塞窗口差异:新建短连接时,TCP慢启动阶段对于500KB大请求来说,很快就能进入高速传输;但长连接闲置后,TCP拥塞窗口会收缩,复用这类连接时,数据传输需重新经历慢启动,导致传输时间变长。
- 服务器调度优先级问题:部分服务器对长连接的请求调度优先级低于新连接,或将长连接请求放入不同处理队列,导致调度延迟增加。
- 测试工具统计逻辑:wrk统计长连接响应时间时,会包含等待前一个请求完成的时间,而短连接的响应时间仅计算单次请求处理时间,统计维度差异导致长连接平均响应时间被高估。
优化方案
- 开启HTTP请求流水线:在HTTP/1.1中启用请求流水线,让同一长连接上的多个请求可并行发起(需服务器支持并行处理),减少串行阻塞影响。
- 调优服务器连接池参数:合理设置长连接空闲超时时间(建议30-60秒),匹配业务并发量调整连接池最大容量,避免连接闲置或不足。
- TCP参数优化:
- 切换到BBR拥塞控制算法,提升长连接传输速率;
- 增大TCP初始拥塞窗口(initcwnd),让长连接复用后快速进入高速传输状态;
- 配置TCP keepalive参数,定期探测连接状态,避免闲置连接拥塞窗口收缩。
- 优化服务器处理能力:
- 精简请求处理逻辑,减少单个请求处理耗时;
- 增加服务器处理线程/进程数,提升并发处理能力,避免请求排队等待。
- 调整测试策略:
- 提高长连接并发数(调大wrk的
-c参数),让连接池充分利用,减少连接闲置; - 延长测试预热时间,等长连接进入稳定状态后再统计响应时间,降低初始波动影响。
- 提高长连接并发数(调大wrk的
- 升级HTTP版本:切换到HTTP/2或HTTP/3,这两个版本原生支持多路复用,同一连接上的多个请求可真正并行处理,彻底解决HTTP/1.1长连接的串行阻塞问题。
内容的提问来源于stack exchange,提问作者taotao
相关产品推荐
相关产品推荐

