场景优化:教师端建立链接 学生利用jmeter端建立链接,心跳维护链接不中断。线程组,下一级ws请求:建立链接,加入课堂。同级ws请求:WebSocket Single Read Sampler 获取服务器数据。教师端进行课件推送到服务器,由于Jmeter这边是持续运行。那么理论WebSocket Single Read Sampler 是可以收到推送课件的数据。进行判定成功收到,学生端向服务端发送消息。停止继续推送课件,否则服务器会一直发送消息,知道第10后中断。
时间: 2025-07-24 18:26:46 浏览: 1
<think>我们正在处理一个持续连接的WebSocket测试场景,需要模拟学生端接收服务器推送的课件数据,并在收到后发送响应消息。关键点包括:
1. 建立持久的WebSocket连接
2. 接收服务器推送的课件消息(可能异步到达)
3. 对接收到的消息进行验证
4. 发送响应消息(例如确认收到)
由于WebSocket Single Read Sampler是单次读取,我们需要设计一个循环读取机制,直到收到预期的消息或超时。
解决方案:
使用While控制器配合计数器实现持续监听,直到收到消息或达到最大重试次数。
步骤:
1. 建立WebSocket连接(WebSocket Open Connection)
2. 发送订阅请求(如果需要,使用WebSocket Single Write Sampler)
3. 使用While控制器循环读取消息,直到收到消息或超时
4. 在循环内使用WebSocket Single Read Sampler读取消息
5. 验证消息内容,如果收到正确的课件消息,则退出循环并发送响应
6. 如果超时未收到,则标记为失败
7. 发送响应消息(例如确认)
8. 关闭连接(可选,如果是持续连接测试可能不立即关闭)
详细步骤:
1. **建立连接**:
- 添加一个`WebSocket Open Connection`取样器,配置服务器URL和连接超时时间,设置一个唯一的Connection ID(例如`${connectionId}`)。
2. **订阅课程**(如果需要):
- 添加`WebSocket Single Write Sampler`,向服务器发送订阅消息,例如:
```json
{"action": "subscribe", "courseId": "${courseId}", "studentId": "${studentId}"}
```
3. **循环读取推送消息**:
- 添加一个`While Controller`,条件设置为`${__javaScript(!vars.get("pushReceived") && ${counter} < ${maxRetry})}`,即未收到消息且重试次数未达到上限时继续循环。
- 在While控制器内:
- 添加一个`计数器`(Counter),用于记录重试次数(例如,计数器名称为`counter`,递增1,起始值1,最大值10,勾选与每用户独立的跟踪计数器)。
- 添加`WebSocket Single Read Sampler`,配置:
- Read Timeout: 设置每次读取等待的超时时间(例如3000毫秒)
- Store Response: 存储响应到变量(例如`response`)
- Connection ID: 与之前设置的相同(`${connectionId}`)
- 添加`JSR223 PostProcessor`(或使用响应断言)来检查读取到的消息。如果消息是课件推送,则设置一个标志变量(例如`pushReceived=true`)并存储消息内容。
```groovy
// 假设服务器推送的消息是JSON格式,包含"type"字段为"material_push"
def response = prev.getResponseDataAsString();
if (response != null && !response.isEmpty()) {
try {
def json = new groovy.json.JsonSlurper().parseText(response)
if (json.type == "material_push") {
vars.put("pushReceived", "true");
vars.put("pushMessage", response); // 存储整个消息
// 可以提取课件URL等信息
vars.put("materialUrl", json.url);
}
} catch (Exception e) {
// 解析失败,不是JSON消息
}
}
```
4. **退出循环后的处理**:
- 检查是否成功收到消息(通过`pushReceived`变量)。如果未收到,则标记为失败(例如使用`SampleResult.setSuccessful(false)`)。
- 如果成功收到,则发送响应消息(例如确认):
- 添加`WebSocket Single Write Sampler`,发送确认消息:
```json
{"action": "ack", "courseId": "${courseId}", "studentId": "${studentId}", "materialUrl": "${materialUrl}"}
```
5. **关闭连接**(根据测试需求,如果是持续连接则可以不关闭,但测试结束时需要关闭):
- 在测试结束时,添加`WebSocket Close Connection`取样器。
6. **超时控制**:
- 在While控制器中,我们通过计数器和每次读取的超时时间来控制总的最大等待时间。例如,每次读取等待3秒,最多重试10次,则总等待时间最多30秒。
7. **断言**:
- 可以添加断言来验证接收到的消息内容是否正确,以及响应消息是否发送成功。
8. **多学生模拟**:
- 使用多个线程(每个线程模拟一个学生),每个线程拥有独立的连接(使用不同的Connection ID)和变量。
注意事项:
- 心跳:如果连接需要保持很长时间,可能需要定时发送心跳(Ping)消息。可以使用`WebSocket Ping/Pong Sampler`。
- 资源清理:确保测试结束后关闭所有连接,避免资源泄漏。
完整测试计划结构示例:
```
线程组(设置线程数模拟多个学生)
│
├─ 配置元件(如HTTP请求默认值、HTTP头管理器等,如果需要)
├─ 用户定义的变量(定义courseId, studentId, maxRetry等)
│
├─ WebSocket Open Connection
├─ WebSocket Single Write Sampler (发送订阅)
├─ While Controller (条件:${__javaScript(!vars.get("pushReceived") && ${counter} < ${maxRetry})})
│ ├─ 计数器(counter)
│ ├─ WebSocket Single Read Sampler
│ └─ JSR223 PostProcessor(处理响应,判断是否收到课件推送)
│
├─ If Controller (条件:${pushReceived} == true)
│ ├─ WebSocket Single Write Sampler (发送确认消息)
│ └─ 断言(验证发送成功)
│
├─ 如果未收到消息,可以添加一个取样器标记失败(例如使用JSR223 Sampler设置失败)
│
└─ WebSocket Close Connection (可选,如果测试结束则关闭)
```
相关问题:
1. 如何在JMeter中模拟多个学生同时接收课件推送?
2. 服务器推送的课件消息是二进制格式(如ProtoBuf)时,如何处理?
3. 如何设置心跳以维持长时间连接?
4. 如何验证接收到的课件消息内容是否正确?</think>### 使用 JMeter 进行 WebSocket 持续连接测试的完整方案
#### **一、测试架构设计**
```mermaid
graph LR
A[教师端] -->|1.推送课件| B(WebSocket服务器)
B -->|2.通知学生| C[JMeter模拟学生端]
C -->|3.接收课件| D{持续连接}
C -->|4.发送响应| B
D -->|心跳维持| E[WebSocket Ping/Pong]
```
#### **二、关键步骤实现**
1. **建立持久化连接**
- 添加 `WebSocket Open Connection` 取样器
- 配置参数:
```properties
Server URL: ws://edu-server/push
Connection Timeout: 30000 ms
Connection ID: ${studentID} // 唯一标识
```
2. **教师推送课件模拟**
使用 `WebSocket Single Write Sampler` 模拟教师操作:
```json
{
"action": "push_material",
"course_id": "math101",
"file_url": "https://edu.com/math101.pdf"
}
```
3. **学生端持续接收与响应**
**核心方案**:使用 `While Controller` + `Single Read Sampler` 实现持续监听
```mermaid
graph TB
W[While Controller] -->|条件| R[${__javaScript(vars.get(''material_received'')!=''true'')}]
R --> S[WebSocket Single Read Sampler]
S --> P[JSR223 PostProcessor]
P --> C{是否课件消息?}
C -->|是| A[发送响应消息]
C -->|否| W
```
**配置细节**:
- **Single Read Sampler**
- Read Timeout: `5000 ms` (短超时保证实时性)
- Store Response: `${ws_response}`
- **响应消息发送** (添加在 While 控制器内)
```groovy
// JSR223 PostProcessor 脚本
def response = vars.get("ws_response");
if (response.contains("math101.pdf")) {
// 1. 标记已接收
vars.put("material_received", "true");
// 2. 发送响应到服务器
ws.sendTextMessage(''{"status":"received","student_id":"${studentID}"}'');
// 3. 记录接收时间
vars.put("receive_time", "${__time()}");
}
```
4. **连接维持机制**
添加 `WebSocket Ping/Pong Sampler`:
```properties
Ping Interval: 20000 ms // 每20秒发送心跳
Timeout: 5000 ms
Connection ID: ${studentID}
```
#### **三、关键验证点**
1. **消息到达验证**
```java
// 响应断言 (检查是否包含课件URL)
Assertion type: Substring
Pattern: https://edu.com/.*\.pdf
Field: ${ws_response}
```
2. **响应延迟测试**
添加 `Duration Assertion`:
```properties
Maximum Time: 3000 ms // 接收后响应需<3秒
```
3. **业务逻辑验证**
```groovy
// JSR223 Assertion 脚本
def response = prev.getResponseDataAsString();
assert response.contains('"status":"received"') : "未发送响应消息";
assert vars.get("receive_time") != null : "未记录接收时间";
```
#### **四、多学生并发测试**
1. **参数化学生信息**
CSV 文件 `students.csv`:
```csv
studentID,token
s01,token_01
s02,token_02
```
- CSV Data Set Config:
```properties
Filename: students.csv
Variable Names: studentID,token
```
2. **连接复用配置**
```properties
// WebSocket Open Connection 高级选项
Re-use connection: ☑️
Max connections: 100 // 连接池大小
```
#### **五、测试结果分析**
| 指标 | 预期值 | 测量方式 |
|------|--------|----------|
| 连接成功率 | $100\%$ | Aggregate Report |
| 平均响应延迟 | $< 1.5s$ | Response Time Graph |
| 消息丢失率 | $0\%$ | 断言失败计数 |
| 最大并发连接 | $500+$ | Stepping Thread Group |
> **关键提示**:
> - 高并发场景启用 **WebSocket Connection Manager** 插件[^1]
> - 二进制协议需使用 `JSR223` 处理序列化[^2]
> - 长时间测试添加 `WebSocket Reconnect` 逻辑[^3]
阅读全文
相关推荐





