1. 为什么你需要这个插件?聊聊JMeter与WebSocket
如果你正在读这篇文章,我猜你多半已经和JMeter打过交道了。这个老牌的性能测试工具,在HTTP协议的世界里,可以说是“一把瑞士军刀”,从接口测试到压力测试,样样精通。但不知道你有没有遇到过这样的场景:公司新项目用上了实时聊天、在线协作、股票行情推送,或者物联网设备状态监控。这些功能背后,往往不再是传统的“请求-响应”模式,而是依赖一种叫WebSocket的长连接协议。这时候,你打开熟悉的JMeter,新建一个HTTP请求采样器,却发现根本连不上——消息发不出去,也收不到服务器的推送。那一刻的无力感,我太懂了。
这就是我们今天要解决的核心问题。JMeter本身并不原生支持WebSocket协议。它默认的采样器都是为HTTP/HTTPS、FTP、JDBC这些设计的。你想测试一个WebSocket服务的并发连接数、消息吞吐量,或者看看在大量消息轰炸下服务会不会崩溃,用原生的JMeter是“巧妇难为无米之炊”。所以,我们需要给它装上“新武器”,也就是JMeter WebSocket Samplers插件。这个插件会为JMeter新增几种专门的采样器,让你能像测试普通HTTP接口一样,去建立WebSocket连接、发送消息、接收消息并做断言。我当年第一次成功配置好,测试了一个实时弹幕服务,那种“通了!”的喜悦,至今记忆犹新。接下来,我就手把手带你,从零开始,把这套“新武器”装备到你的JMeter上,并把它调教好。
2. 搭建你的测试舞台:JMeter与Java环境准备
工欲善其事,必先利其器。在安装插件之前,我们得先把基础舞台搭好。这里主要有两位主角:Java运行环境和JMeter本身。别看是基础步骤,这里面的坑我踩过不少,咱们一步步来,避开它们。
2.1 搞定Java环境:选对版本是关键
JMeter是用Java写的,所以它离不开Java运行时环境(JRE)。但请注意,并不是Java版本越新越好。JMeter社区对新版本Java的适配通常会滞后一些。根据我多年的经验,为了最大的兼容性和稳定性,我强烈推荐使用 Java 8 或者 Java 11 的LTS(长期支持)版本。尤其是Java 8,依然是目前最广泛支持、问题最少的版本。
怎么检查你电脑上有没有Java,以及是什么版本呢?很简单,打开你的命令行终端(Windows上是CMD或PowerShell,Mac或Linux上是Terminal),输入下面的命令:
java -version
敲下回车,你会看到类似这样的信息:
openjdk version "1.8.0_392"
OpenJDK Runtime Environment (build 1.8.0_392-b08)
OpenJDK 64-Bit Server VM (build 25.392-b08, mixed mode)
如果看到了版本号,并且确实是8或11,那么恭喜你,这一步可以跳过了。如果提示“不是内部或外部命令”,那就说明你还没安装Java。
去哪里下载呢?我建议直接去Oracle官网下载Java 8(JDK 8),或者选择开源的OpenJDK发行版,比如Adoptium(原名AdoptOpenJDK)提供的版本。安装过程就是一路“下一步”,安装完成后,记得要配置一个叫 JAVA_HOME 的环境变量,它的值就是你Java安装的根目录(比如C:\Program Files\Java\jdk1.8.0_392)。然后再把%JAVA_HOME%\bin(Windows)或$JAVA_HOME/bin(Mac/Linux)添加到系统的PATH环境变量里。这样,在任何地方命令行都能识别java命令了。配置完环境变量后,务必重新打开你的命令行窗口,再执行java -version来验证是否成功。
2.2 下载与安装JMeter:认准官方渠道
基础打牢了,现在来请出今天的主演——JMeter。我的原则是:软件类工具,尤其是开发测试工具,一定要从官方渠道下载。这能避免捆绑软件、恶意篡改,也能确保你拿到的是最新的稳定版。
JMeter的官方下载地址是 Apache 软件基金会的镜像站。你可以直接访问:
https://jmeter.apache.org/download_jmeter.cgi
这个页面会列出最新的版本。通常,我们选择“Binaries”版本,也就是编译好的、可以直接运行的版本。你会看到一个.zip格式的压缩包(Windows用户)和一个.tgz格式的压缩包(Linux/Mac用户)。直接点击下载即可。我写这篇文章时,最新的稳定版是5.6.3,但你下载时可能已经有更新版了,用最新的就行。
下载完成后,得到一个压缩包,比如apache-jmeter-5.6.3.zip。接下来就是“安装”了,其实对于JMeter来说,安装就是解压。找一个你喜欢的路径,比如D:\Tools或者/Users/YourName/Applications,把压缩包解压进去。解压后,你会看到一个名为apache-jmeter-5.6.3的文件夹,这里面就是JMeter的全部家当。
为了以后启动方便,我建议你把JMeter的bin目录也添加到系统的PATH环境变量里。这样,你就可以在命令行里直接输入jmeter来启动它了。不过,对于新手来说,最简单的方式是直接进入解压后的bin目录,找到启动脚本。Windows用户双击jmeter.bat,Mac/Linux用户双击jmeter.sh(或在终端里执行./jmeter.sh)。如果一切顺利,你会看到JMeter的图形化界面缓缓打开。第一次启动可能会慢一点,因为它要初始化一些组件。
3. 获取核心武器:WebSocket插件的两种安装方式
JMeter本身已经就绪,现在我们来获取最重要的扩展模块——WebSocket插件。这里我提供两种主流的安装方法,各有优劣,我会详细说明,你可以根据你的网络情况和习惯来选择。
3.1 方式一:手动下载与安装(最稳定可靠)
这是最传统,也是我最推荐给新手的方-法。虽然步骤稍多,但每一步都在你的掌控之中,尤其适合网络环境不稳定、或者无法直接访问某些资源库的情况。
首先,我们需要找到这个插件的“家”。目前最流行、维护相对活跃的JMeter WebSocket插件,是由社区开发者维护的,你可以在Bitbucket上找到它。直接访问项目的发布页面:
https://bitbucket.org/pjtr/jmeter-websocket-samplers/downloads/
打开这个页面,你会看到一系列以.jar结尾的文件。你需要下载两个核心的JAR包:
jmeter-websocket-samplers-xxx.jar:这是插件的主文件,包含了所有的WebSocket采样器逻辑。xxx是版本号,请下载最新的版本。jetty-http-xxx.jar和jetty-io-xxx.jar等依赖包:WebSocket插件依赖于Eclipse Jetty这个库来实现WebSocket客户端功能。通常,在下载页面,作者会提供一个包含所有依赖的“with-dependencies”的包,或者列出所有必需的依赖JAR。请务必下载页面中列出的所有相关JAR文件。缺少依赖是插件安装失败最常见的原因。
下载好这一堆.jar文件后,安装就简单了。找到你的JMeter安装目录,里面有一个叫lib的文件夹,还有一个叫lib/ext的文件夹。你需要将所有下载的JAR文件,全部复制到lib/ext目录下。这个ext目录就是JMeter存放扩展插件的地方。
复制完成后,彻底关闭你已经打开的JMeter图形界面。然后重新启动JMeter。如果安装成功,当你右键点击“测试计划” -> “添加” -> “取样器”时,你应该能在列表的靠下部分看到新增的WebSocket相关采样器,比如“WebSocket Open Connection”、“WebSocket request-response Sampler”等。看到它们,就说明手动安装成功了!
3.2 方式二:使用插件管理器安装(最方便快捷)
如果你觉得手动下载依赖太麻烦,或者想更方便地管理未来其他的JMeter插件,那么JMeter Plugins Manager(插件管理器)是你的不二之选。它就像一个JMeter的“应用商店”,可以一键搜索、安装、升级和卸载插件。
首先,你需要安装这个插件管理器本身。它也是一个JAR文件。访问插件的官方网站:
https://jmeter-plugins.org/wiki/PluginsManager/
在页面上找到名为 jmeter-plugins-manager-xxx.jar 的文件并下载。然后,和手动安装插件一样,将这个JAR文件复制到JMeter的lib/ext目录下。重启JMeter。
重启后,你会在JMeter的顶部菜单栏“选项”(Options)下,看到一个新的菜单项“Plugins Manager”。点击它,会打开一个插件管理窗口。这个窗口里有很多标签页,比如“Available Plugins”(可用插件)、“Installed Plugins”(已安装插件)等。
我们要安装WebSocket插件,就切换到“Available Plugins”标签页。在右上角的搜索框里,输入“WebSocket”进行搜索。在搜索结果列表中,你应该能找到类似“WebSocket Samplers by Peter Doornbosch”这样的条目(Peter Doornbosch是原作者pjtr的名字)。勾选它前面的复选框。
这里有个非常重要的细节:在插件管理器的列表中,你可能会看到同一个插件有多个版本或变体。请务必选择那个带有依赖项的版本,通常描述里会写明“with dependencies”。直接勾选基础版本可能会导致依赖缺失。勾选好后,点击右下角的“Apply Changes and Restart JMeter”按钮。管理器会自动下载插件及其所有依赖,安装完成后会提示你重启JMeter。重启后,WebSocket采样器就应该出现在你的取样器列表里了。
两种方式怎么选? 我个人的经验是:如果是在公司内网环境,或者你需要确保测试环境与某个特定版本完全一致,手动安装更可控。如果是个人学习、快速搭建,或者网络通畅,插件管理器无疑更方便,未来管理其他插件(比如后面会提到的性能监控插件、线程组插件等)也更省心。
4. 深入插件核心:三大采样器详解与实战配置
插件安装成功,只是拥有了武器。要想在战场上得心应手,你必须了解每件武器的特性、射程和用法。JMeter WebSocket插件主要提供了三种核心采样器,它们分别对应WebSocket通信生命周期的不同阶段。我们来一个个拆解,并配上详细的配置截图和参数说明。
4.1 WebSocket Open Connection:建立握手连接
你可以把它想象成“拨电话”的动作。在能通话之前,必须先建立连接。这个采样器就是用来向服务器发起WebSocket握手请求,并维持这个长连接的。
添加一个“WebSocket Open Connection”采样器,你会看到这些关键配置项:
- WebSocket Server:这里填你的WebSocket服务器地址。注意,URL的格式是
ws://或wss://开头,而不是HTTP的http://。例如,ws://echo.websocket.org是一个公开的WebSocket测试服务器。如果是安全的WebSocket,则是wss://your-server.com/path。 - Connection Timeout:连接超时时间(毫秒)。如果服务器在这个时间内没有响应,则视为连接失败。根据网络情况设置,一般5000(5秒)足够。
- Read Timeout:读取超时。这个参数很重要!它定义了在连接建立后,等待服务器发送数据的超时时间。对于需要服务器主动推送的场景,这个值要设得大一些,比如设成
0表示永不超时,或者设一个很大的数字(如300000,即5分钟)。如果设得太小,JMeter可能会在等待推送时误认为连接超时而关闭它。 - Connection ID:连接标识符。这是一个极其重要的参数!当你的测试计划中需要建立多个WebSocket连接,或者后续的发送/接收采样器需要指定使用哪个连接时,就靠这个ID来区分。你可以给它起个名字,比如
ChatConnection_1。后续的所有操作,只要指定相同的Connection ID,就会复用这个连接。
配置好后,运行一下这个采样器,在“查看结果树”里看看。如果成功,响应数据里会看到“Connection established”之类的信息,并且响应代码应该是101(Switching Protocols)。
4.2 WebSocket request-response Sampler:一问一答
这是最常用的采样器,模拟客户端发送一条消息,然后等待并接收服务器针对这条消息的回复。就像你发一条微信,等待对方回复。
它的配置界面包含了“WebSocket Open Connection”的所有配置项(因为如果连接不存在,它也可以自己先建立连接),并增加了几个核心字段:
- Request Data:你要发送给服务器的消息内容。可以是纯文本、JSON字符串等等。这里支持JMeter变量,比如你可以用
${message}来参数化发送的内容。 - Close Connection:勾选后,会在收到本次响应后自动关闭WebSocket连接。通常不勾选,以保持长连接进行后续测试。
- Response Timeout:等待服务器响应的超时时间。发送消息后,如果在这个时间内没收到回复,采样器就认为失败。
这个采样器的工作流程是:发送Request Data -> 等待 -> 接收一条消息 -> 结束。它默认只等待并接收一条消息。如果服务器在你发送后,连续推送了好几条消息,这个采样器只会读到第一条,后面的消息会滞留在缓冲区,可能导致后续测试混乱。这点需要特别注意。
4.3 WebSocket Single Read Sampler:专注聆听
这个采样器是“只接收,不发送”。它用于模拟这样的场景:连接已经建立,客户端静静地等待服务器主动推送消息。比如监控股票行情、接收聊天室广播。
它的配置相对简单:
- Connection ID:指定要监听哪个已建立的连接。
- Read Timeout:等待消息的超时时间。和Open Connection里的类似,如果设得太短,可能还没等到推送就超时了;如果设
0,则会一直阻塞直到收到消息。 - Close Connection:收到消息后是否关闭连接。
这个采样器会一直等待,直到超时或者收到一条消息就返回。如果你想持续监听多条推送消息,就需要在循环控制器里多次使用这个采样器,或者配合While控制器使用。
4.4 组织你的测试逻辑:控制器与断言
单单有采样器还不够,我们需要用JMeter的“骨架”——逻辑控制器,把它们有机组织起来,模拟真实的用户行为。
一个典型的WebSocket压力测试线程组可能是这样的结构:
线程组 (模拟10个并发用户)
├── 循环控制器 (每个用户循环执行100次)
│ ├── WebSocket Open Connection (Connection ID = WS_${__threadNum})
│ ├── 思考时间定时器 (模拟用户停顿)
│ ├── WebSocket request-response Sampler (发送一条消息,等待回复)
│ ├── JSON提取器/正则表达式提取器 (从回复中提取关键数据,存入变量)
│ ├── 响应断言 (检查回复内容是否正确)
│ ├── WebSocket Single Read Sampler (可选,监听额外推送)
│ └── 思考时间定时器
└── WebSocket Close Sampler (循环结束后,关闭连接)
这里的关键点是:
- 变量化Connection ID:使用
${__threadNum}函数,让每个虚拟用户(线程)建立自己独立的连接,避免互相干扰。这是模拟真实并发的基础。 - 使用断言:在“WebSocket request-response Sampler”下添加“响应断言”,来验证服务器返回的消息是否符合预期。断言可以检查响应文本是否包含某个关键字,或者用JSON断言检查某个字段的值。
- 使用定时器:在操作之间添加“固定定时器”或“高斯随机定时器”,用来模拟用户操作之间的思考、停顿时间,让测试压力曲线更真实,而不是一股脑的洪水攻击。
5. 从理论到实战:构建一个完整的WebSocket测试计划
光说不练假把式。现在,我们用一个实际的例子,把前面所有的知识串起来。假设我们要测试一个简单的“在线聊天室”服务,功能是:用户连接后,发送一条消息,服务器会回复一条包含原消息和时间的确认信息。
步骤1:创建测试计划与线程组
- 启动JMeter,测试计划名称可以改为“WebSocket聊天室压力测试”。
- 右键测试计划 -> 添加 -> 线程(用户) -> 线程组。我们设置:线程数(用户数)为5,Ramp-Up时间为2秒,循环次数为10。意思是5个用户在2秒内陆续启动,每个用户执行10轮聊天操作。
步骤2:建立WebSocket连接
- 右键线程组 -> 添加 -> 取样器 -> 选择“WebSocket Open Connection”。
- 名称:改为“01-建立聊天连接”。
- WebSocket Server:这里我们需要一个真实的测试服务器。我们可以使用一个免费的在线WebSocket回显服务,比如
wss://echo.websocket.org。注意,我们用了wss,表示安全的WebSocket。 - Connection Timeout:设为5000。
- Read Timeout:设为60000(因为我们要等服务器推送,设长一点)。
- Connection ID:填入
Chat_${__threadNum}。这样,线程1的连接ID就是Chat_1,线程2是Chat_2,以此类推。
步骤3:发送聊天消息
- 在“01-建立聊天连接”采样器下,右键 -> 添加 -> 定时器 -> 固定定时器。设置线程延迟为1000毫秒,模拟用户连接后稍微停顿一下。
- 右键线程组 -> 添加 -> 取样器 -> 选择“WebSocket request-response Sampler”。
- 名称:改为“02-发送并接收消息”。
- WebSocket Server:留空即可(因为它会复用上面定义的Connection ID对应的连接)。
- Connection ID:填入
Chat_${__threadNum}。这里必须和Open Connection中的ID一致! - Request Data:填入我们要发送的消息,例如
{"user": "User_${__threadNum}", "msg": "Hello, Server!"}。这里我们用了JMeter变量让每个用户发送的消息略有不同。 - Response Timeout:设为5000。
步骤4:验证服务器响应
- 选中“02-发送并接收消息”采样器,右键 -> 添加 -> 断言 -> 响应断言。
- 我们假设服务器会返回一个JSON,里面包含我们发送的
msg字段。在响应断言中:- 测试字段:选择“响应文本”。
- 模式匹配规则:选择“包含”。
- 要测试的模式:添加
"Hello, Server!"。这样就能断言回复中是否包含了我们发送的文本。
步骤5:添加监听器查看结果
- 右键线程组 -> 添加 -> 监听器 -> 查看结果树。运行测试后,可以在这里看到每个采样器请求和响应的详细信息,用于调试。
- 右键线程组 -> 添加 -> 监听器 -> 聚合报告。这是性能测试的核心,运行结束后可以看到请求数、平均响应时间、错误率等关键性能指标。
步骤6:运行与调试
点击工具栏的绿色开始按钮运行测试。在“查看结果树”中,依次点击各个采样器,检查“响应数据”选项卡。你应该能看到“01-建立聊天连接”返回连接成功的状态,而“02-发送并接收消息”的响应数据中,应该能看到我们发送的Hello, Server!消息被服务器原样返回(因为用的是回显服务器)。如果响应断言失败,结果树中该采样器会显示为红色。
通过这个完整的例子,你就拥有了一个可运行、可扩展的WebSocket测试脚本基础。你可以在此基础上,增加更多的消息发送、模拟不同的消息类型、加入更多的断言,或者调整线程组的参数来进行压力测试。
6. 避坑指南:那些年我踩过的常见问题
即使按照步骤一步步来,在实际操作中你还是可能会遇到一些让人头疼的问题。下面是我总结的几个最常见的“坑”及其解决方案,希望能帮你节省大量排查时间。
问题一:插件安装后,在JMeter里找不到WebSocket采样器。
- 可能原因1:JAR文件放错了位置。 确保所有下载的JAR文件都放在了
lib/ext目录下,而不是lib目录。 - 可能原因2:依赖缺失。 这是手动安装时最常见的问题。WebSocket插件依赖Jetty等库,你必须确保所有必要的依赖JAR都下载并放入了
lib/ext。最稳妥的方法是下载插件页面提供的“-with-dependencies”包,或者仔细阅读下载说明,把所有列出的JAR都下载下来。 - 可能原因3:JMeter未重启。 放入JAR后,必须完全关闭JMeter图形界面并重新启动,新的插件才会被加载。
- 排查方法:启动JMeter时,观察命令行窗口(如果是从命令行启动的)或日志文件(位于
bin目录下的jmeter.log)。如果插件加载失败,通常会有相关的错误信息打印出来,比如“ClassNotFoundException”,这能帮你定位是哪个类库缺失。
问题二:WebSocket连接失败,响应代码不是101。
- 可能原因1:服务器地址或协议写错。 再次确认URL是
ws://或wss://开头,并且端口号正确。WebSocket默认端口是80(ws)或443(wss),但如果服务部署在其他端口,需要显式指定,如ws://localhost:8080/chat。 - 可能原因2:服务器需要特定的子协议(Subprotocol)。 有些WebSocket服务要求客户端在握手时声明使用的子协议(比如
soap,wamp等)。在“WebSocket Open Connection”采样器的“Implementation Parameters”区域(可能需要展开高级选项),查找是否有设置子协议的地方。插件的不同版本位置可能不同,有些版本直接在主界面有“Protocol”输入框。 - 可能原因3:服务器有认证要求。 如果服务需要HTTP头部认证(如Token、Cookie),你需要在连接之前,通过一个HTTP请求采样器先完成登录,获取认证信息,然后通过“HTTP Cookie管理器”或“HTTP头管理器”将Cookie或Token传递给WebSocket连接。WebSocket握手本身是一个HTTP升级请求,会携带这些头部信息。
问题三:能连接,但发送消息后收不到回复,或者回复不对。
- 可能原因1:Request Data格式错误。 如果服务器期望接收JSON,而你发送的是纯文本,或者JSON格式有误(缺少引号、括号),服务器可能无法解析,也就不会返回预期的响应。使用在线JSON格式化工具检查你的消息格式。
- 可能原因2:Response Timeout设置过短。 服务器处理可能需要时间,如果超时时间设得太短(比如100毫秒),可能还没等到回复采样器就超时结束了。适当调大这个值。
- 可能原因3:消息粘包或缓冲区问题。 正如前面提到的,
request-response采样器默认只读取一条响应。如果服务器快速连续推送了多条消息,可能会被后面的采样器读到,导致断言失败。在设计测试脚本时,要清楚服务器端的响应模式。
问题四:在压力测试下,连接数上不去或大量报错。
- 可能原因1:本地端口耗尽。 每个WebSocket连接都会占用一个本地端口。当模拟成千上万的并发连接时,操作系统可用的临时端口(通常范围是1024-65535)可能会被快速耗尽。在Windows或Linux上,可以调整系统的临时端口范围来增加上限。
- 可能原因2:JMeter自身资源不足。 高并发测试会消耗大量内存和CPU。确保运行JMeter的机器配置足够,并在JMeter的启动脚本(
jmeter.bat或jmeter.sh)中调整JVM堆内存参数(如-Xms2g -Xmx4g)。 - 可能原因3:网络带宽或服务器瓶颈。 使用“聚合报告”和“每秒事务数”等监听器监控性能指标。如果响应时间随着并发增加而急剧上升,错误率提高,很可能是达到了服务器或网络的瓶颈。此时需要结合服务器监控(如使用JMeter的PerfMon插件监控服务器CPU、内存)来综合分析。
记住,性能测试本身就是一个“发现-分析-解决”问题的过程。遇到问题别慌,善用“查看结果树”查看原始请求和响应,结合日志分析,大部分问题都能定位。

296

被折叠的 条评论
为什么被折叠?



