使用JMeter进行WebSocket负载测试时的线程和消息序列处理
首先,我对JMeter很陌生。 我正在尝试对websocket服务进行负载测试,但我还没有弄清楚如何在收到对前一条消息的响应后,在有限数量的并发连接中,在一个连接内顺序(而不是与其他线程并行)发送多条消息 我的连接也不会关闭,因为如果找到响应模式,则无法识别关闭模式 更新 修改WebSocketSampler代码后,消息特定的匹配模式和匹配与关闭都可以工作;代码最终会发生变化 本例的目标使用JMeter进行WebSocket负载测试时的线程和消息序列处理,websocket,jmeter,jmeter-plugins,Websocket,Jmeter,Jmeter Plugins,首先,我对JMeter很陌生。 我正在尝试对websocket服务进行负载测试,但我还没有弄清楚如何在收到对前一条消息的响应后,在有限数量的并发连接中,在一个连接内顺序(而不是与其他线程并行)发送多条消息 我的连接也不会关闭,因为如果找到响应模式,则无法识别关闭模式 更新 修改WebSocketSampler代码后,消息特定的匹配模式和匹配与关闭都可以工作;代码最终会发生变化 本例的目标 打开总共12个连接(3个并发连接,在上一个连接关闭后打开新连接) 向每个连接发送5条消息 每条消息都包含
- 打开总共12个连接(3个并发连接,在上一个连接关闭后打开新连接)
- 向每个连接发送5条消息
- 每条消息都包含格式为“messageIx”:n的键值对(其中n是1到5之间的整数)
- 等待,直到收到包含相同密钥的第一个响应
- 发送下一条消息
- 当收到包含“messageIx”:5的响应时,关闭连接
- 螺纹组
- 3线程
- 加速1秒
- 循环计数5
- 网袋取样器
- 连接超时5000ms
- 响应超时5000ms
- 请求数据${Request}
- 响应模式${Response}
- 关闭连接模式\“messageIx\”:5
- CSV数据集配置
- 变量名请求、响应
- 共享模式当前线程
- 定界符李>
- 在EOF上循环使用False
- EOF上的停止线程:True
{"messageType":0,"messageIx":1,"action":"None"};"messageIx":1
{"messageType":0,"messageIx":2,"action":"None"};"messageIx":2
{"messageType":0,"messageIx":3,"action":"None"};"messageIx":3
{"messageType":0,"messageIx":4,"action":"None"};"messageIx":4
{"messageType":0,"messageIx":5,"action":"Close"};"messageIx":5
对SimpleWebSocketServer(python)实现输出运行此配置是非常困难的
52682 : connected
52682 <-- {"messageType":0,"messageIx":1,"action":"None"}
52691 : connected
52691 <-- {"messageType":0,"messageIx":1,"action":"None"}
52700 : connected
52700 <-- {"messageType":0,"messageIx":1,"action":"None"}
52682 <-- {"messageType":0,"messageIx":2,"action":"None"}
52691 <-- {"messageType":0,"messageIx":2,"action":"None"}
52700 <-- {"messageType":0,"messageIx":2,"action":"None"}
52682 <-- {"messageType":0,"messageIx":3,"action":"None"}
52691 <-- {"messageType":0,"messageIx":3,"action":"None"}
52700 <-- {"messageType":0,"messageIx":3,"action":"None"}
52682 <-- {"messageType":0,"messageIx":4,"action":"None"}
52691 <-- {"messageType":0,"messageIx":4,"action":"None"}
52700 <-- {"messageType":0,"messageIx":4,"action":"None"}
52682 <-- {"messageType":0,"messageIx":5,"action":"Close"}
52691 <-- {"messageType":0,"messageIx":5,"action":"Close"}
52700 <-- {"messageType":0,"messageIx":5,"action":"Close"}
52682 <-- <EOF>
52691 <-- <EOF>
52700 <-- <EOF>
52682 <-- <EOF>
52691 <-- <EOF>
52700 <-- <EOF>
52691 : closed
52682 : closed
52700 : closed
但对于以下消息,没有匹配项
[Execution Flow]
- Reusing exising connection
- Waiting for messages for 5000 MILLISECONDS
- Received message #2 (47 bytes); didn't match any pattern
- Leaving streaming connection open
对于线程的最后一条消息,除了客户端关闭连接外,数据是相同的(但流连接保持打开状态)
但是,如果我将响应模式修改为泛型\“messageIx\”:所有消息都匹配,但关闭连接与\“messageIx\”:5或关闭模式都不匹配
Response data:
[Message 5]
{"messageType":0,"messageIx":5,"action":"Close"}
Sampler request:
[Execution Flow]
- Reusing exising connection
- Waiting for messages for 5000 MILLISECONDS
- Received message #5 (48 bytes); matched response pattern
- Leaving streaming connection open
最后,线程。如果我设置了12个线程,它们在开始时都会有上升延迟。
添加循环控制器只会增加同一连接的消息,增加线程组中的循环(并在csv读取器中使用循环)将失败,因为连接已经关闭(如果关闭连接模式匹配)
我在寻找帮助
boolean matchFound = false;
if (responseExpression == null || responseExpression.matcher(msg).find()) {
logMessage.append("; matched response pattern");
closeLatch.countDown();
matchFound = true;
}
if (!disconnectPattern.isEmpty() && disconnectExpression.matcher(msg).find()) {
logMessage.append("; matched connection close pattern").append("\n");
closeLatch.countDown();
matchFound = true;
close(StatusCode.NORMAL, "JMeter closed session.");
}
if (!matchFound)
{
logMessage.append("; didn't match any pattern").append("\n");
} else {
logMessage.append("\n");
}
我以前从未编写过Java——如果我所应用的更改是合理的,我将非常感谢更有经验的人发表评论
现在我可以单独匹配消息,也可以关闭连接。仍在寻找有关限制并发线程数量的帮助,而不必为消息重复使用相同的连接
更新2:重新连接
限制并发用户数(连接数)的一种方法是使用CSV文件作为源,并将EOF上的recycle设置为true,将threads设置为并发目标,将loop count设置为每个线程的连接数乘以CSV文件中的消息数
在1.0.2上,这不会直接起作用,因为connectionId不会改变,插件尝试使用旧的、封闭的连接。在WebSocketSamples.java上,第69行:
if (isStreamingConnection()) {
if (connectionList.containsKey(connectionId)) {
socket = connectionList.get(connectionId);
if (socket.isConnected()){
socket.initialize(this);
return socket;
}
connectionList.remove(connectionId, socket);
}
修改似乎起到了作用。与基于Node.JS的Thor相比,消息似乎仍然是并行发送的,性能似乎相当差:(
boolean matchFound = false;
if (responseExpression == null || responseExpression.matcher(msg).find()) {
logMessage.append("; matched response pattern");
closeLatch.countDown();
matchFound = true;
}
if (!disconnectPattern.isEmpty() && disconnectExpression.matcher(msg).find()) {
logMessage.append("; matched connection close pattern").append("\n");
closeLatch.countDown();
matchFound = true;
close(StatusCode.NORMAL, "JMeter closed session.");
}
if (!matchFound)
{
logMessage.append("; didn't match any pattern").append("\n");
} else {
logMessage.append("\n");
}
if (isStreamingConnection()) {
if (connectionList.containsKey(connectionId)) {
socket = connectionList.get(connectionId);
if (socket.isConnected()){
socket.initialize(this);
return socket;
}
connectionList.remove(connectionId, socket);
}