JMeter压测WebSocket连接数的核心是维持长连接而非发请求,必须用WebSocket Open Connection配合线程组生命周期控制,否则线程数不等于真实连接数;因默认线程执行完即释放资源,若不显式管理连接,会反复新建/关闭,导致实际并发连接远低于设定线程数。

直接说结论:JMeter 压测 WebSocket 连接数,核心不是“发多少请求”,而是“维持多少长连接”,必须用 WebSocket Open Connection + WebSocket request-response 配合线程组生命周期来控制,否则压出来的根本不是真实连接数。
为什么线程数 ≠ WebSocket 连接数?
很多人把线程组里设 1000 线程,就以为压出了 1000 个 WebSocket 连接——这是最大误区。JMeter 默认每个线程执行完 Sampler 就释放资源,如果没显式管理连接生命周期,WebSocket request-response 可能反复新建/关闭连接,实际并发连接数远低于线程数。
- 必须确保每个线程只执行一次
WebSocket Open Connection,且后续所有消息都在该连接上发送 -
WebSocket Open Connection要放在线程组最开头,且勾选 “Close connection on thread exit”(默认不勾选,不关才对) - 避免在循环控制器里重复调用
WebSocket Open Connection,否则每轮都重连 - 若使用 CSV 参数化用户 ID,需确认服务端允许同一 IP 多连接;某些 Nginx 或负载均衡器会限制 per-IP 连接数
如何正确配置连接建立与保活
连接建立阶段最容易失败,错误常表现为 java.net.ConnectException: Connection refused 或握手超时,本质是 Upgrade 请求被拦截或参数错配。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
-
Server URL必须完整,如ws://example.com/chat?token=abc,query 参数不能丢 -
Connection Timeout建议设为 5000–10000ms,尤其当后端有鉴权或数据库查用户时延较高 - 若服务端要求自定义 Header(如
Authorization、X-User-ID),必须添加Header Manager,不是填在 URL 里 - WSS 场景下,需提前在 JMeter 的
system.properties中配置javax.net.ssl.trustStore,否则报SSLHandshakeException - 心跳不是可选项:用
Constant Timer或JSR223 Timer每 30s 发一次Ping帧(可用WebSocket Ping FrameSampler),否则连接大概率被中间设备(NAT、防火墙)静默断开
高并发下连接数上不去的常见卡点
设了 5000 线程,结果监控显示服务器只收到 800 个连接?问题往往不在 JMeter 脚本,而在环境或协议层。
- JMeter 本机文件描述符限制:Linux 下默认
ulimit -n是 1024,需改到 65535+,否则大量java.io.IOException: Too many open files - Windows 上单机压测超过 2000 连接极不稳定,建议用多台 JMeter 从机分布式压测
- Nginx 配置漏了
proxy_http_version 1.1和proxy_set_header Upgrade $http_upgrade,导致 Upgrade 头被丢弃,服务端收不到握手请求 - 服务端未调大
net.core.somaxconn和net.ipv4.tcp_max_syn_backlog,SYN 队列溢出,连接直接被丢弃 - 插件版本不匹配:JMeter 5.6+ 必须用
jmeter-websocket-samplers-1.2.10.jar或更高,旧版(如 1.2.8)在高并发下有连接泄漏 bug
怎么验证你真的压出了目标连接数?
别只看 JMeter 的聚合报告,那里的 “Samples” 是消息数,不是连接数。真正有效的验证方式只有两个:
- 服务端实时统计:在业务代码里用
ConcurrentHashMap或 Redis 记录在线连接 ID,暴露一个 HTTP 接口返回当前连接数,压测中轮询调用 - 系统级观测:Linux 上执行
ss -s | grep "tcp"查 ESTAB 状态数,或netstat -an | grep :8080 | grep ESTAB | wc -l,注意过滤掉 TIME_WAIT - 抓包确认:用
tshark -i any -Y "websocket && tcp.port==8080" -T fields -e ip.src -e websocket.handshake.key,看握手包数量是否匹配预期 - 关键提醒:JMeter 的
Active Threads Over Time图显示的是“活跃线程数”,它和连接数仅在“每个线程持有一个连接”且“不主动关闭”的前提下才近似相等——这个前提必须手动保障,不是自动成立的

















