英文:
locust mixed rest and websocket performance testing on the same locustfile
问题
我试图编写一个具有以下要求的测试:
- 测试包括两个调用,这两个调用必须按顺序执行。
- 第一个调用是一个REST调用(HTTP POST)。
- 第二个调用是一个WebSocket调用。
我如何可以在同一个Locust文件中实现这一点?这是可能的吗?
这是我的测试:
import time
import json
import logging
import re
import gevent
import websocket
from locust import User, FastHttpUser, SequentialTaskSet, task, between
headers = [
"auth: headers",
]
class MySocketUserClass(User):
# ...(你的WebSocket相关代码)...
class WebSocketCall(MySocketUserClass):
@task
def my_task(self):
self.connect("wss://example.com", header=headers)
# 示例订阅
self.send({'example': 'payload'})
# 等待附加的推送,同时偶尔发送心跳,就像真实客户端一样
self.sleep_with_heartbeat(10)
def on_message(self, message):
# TO BE IMPLEMENTED
pass
class RestCall(FastHttpUser):
# ...(你的REST调用相关代码)...
class UserBehaviour(SequentialTaskSet):
tasks = [RestCall, WebSocketCall]
但只有RestCall被执行。
英文:
I'm trying to write a test with the following requirementes:
- the test has two calls, the calls has to be exectuted in sequence
- the first call is a REST call (http post)
- the second one is a websocket call
How I can implement this in the same locustfile?
Is this possible?
This is my test:
import time
import json
import logging
import re
import gevent
import websocket
from locust import User, FastHttpUser, SequentialTaskSet, task, between
headers = [
"auth: headers",
]
class MySocketUserClass(User):
def connect(self, host: str, header=[], **kwargs):
self.ws = websocket.create_connection(host, header=header, **kwargs)
gevent.spawn(self.receive_loop)
def send(self, body, context={}):
self.environment.events.request.fire(
request_type="WSS",
name='test',
response_time=None,
response_length=len(body),
exception=None,
context={**self.context(), **context},
)
logging.debug(f"WSS: {body}")
self.ws.send(json.dumps(body))
def on_message(self, message): # override this method in your subclass for custom handling
print(message)
self.environment.events.request.fire(
request_type="WSR",
name='test',
response_time=0,
response_length=len(message),
exception=None,
context=self.context(),
)
def receive_loop(self):
while True:
message = self.ws.recv()
logging.debug(f"WSR: {message}")
self.on_message(message)
def sleep_with_heartbeat(self, seconds):
while seconds >= 0:
gevent.sleep(min(15, seconds))
seconds -= 15
self.send({})
class WebSocketCall(MySocketUserClass):
@task
def my_task(self):
self.connect("wss://example.com", header=headers)
# example of subscribe
self.send({'example': 'payload'})
# wait for additional pushes, while occasionally sending heartbeats, like a real client would
self.sleep_with_heartbeat(10)
def on_message(self, message):
# TO BE IMPLEMENTED
pass
class RestCall(FastHttpUser):
default_headers = {
"accept": "application/json",
"accept-encoding": "gzip, deflate, br",
"accept-language": "en-US,en;q=0.9,it;q=0.8",
"content-type": "application/json",
"sec-ch-ua": '"Chromium";v="110", "Not A(Brand";v="24", "Microsoft Edge";v="110"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"',
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.50",
"origin": "https://example.com",
"referer": "https://example.com",
}
def call_rest(self):
self.iam = 'rest'
with self.rest(
"POST",
"https://example.com",
json={
"example": "payload"
},
) as resp:
# CHECK RESPONSE
print(resp)
@task
def sent1(self):
self.call_rest()
class UserBehaviour(SequentialTaskSet):
tasks = [RestCall, WebSocketCall]
but only the RestCall is executed
答案1
得分: 0
问题可能在于你将多个Users
放入了SequentialTaskSet
任务中。我之前没见过有人这样做,所以我不知道行为会是什么样。我建议将你的MySocketUserClass
设置为一个不继承自User
的泛型类对象。你可以在初始化时传入environment
,以便仍然可以触发事件。然后,不要再创建WebSocketCall
作为另一个类,只需将task
作为SequentialTaskSet
内的函数即可。对于RestCallUser
,你也可以做同样的事情。然后,创建一个FastHttpUser
,将SequentialTaskSet
作为其tasks
。查看此Stack Overflow问题以获取示例:
https://stackoverflow.com/a/63573818/7355637
或者,你也可以不使用SequentialTaskSet
,而是将sent1
任务变得更通用,并在同一个任务内首先调用你的websocket my_task
相关的内容。一个单一任务中可以包含多个函数调用。Locust仍然会适当地触发任何事件。
英文:
The problem may be that you're putting multiple Users
in your SequentialTaskSet
tasks. I haven't seen anyone do that before so I don't know what the behavior would be. I'd recommend making your MySocketUserClass
a generic class object that doesn't inherit from User
. You could make it take the environment
on init so it could still fire events. Then instead of having WebSocketCall
be yet another class, just make the task
a function inside the SequentialTaskSet
. You can actually do the same for RestCallUser
. Then you make a FastHttpUser
with the SequentialTaskSet
as its tasks
. See this SO question for an example:
https://stackoverflow.com/a/63573818/7355637
Alternatively, you can also just not use SequentialTaskSet
and instead make the sent1
task more generic and call your websocket my_task
stuff first inside the same task. A single task can include multiple function calls inside it. Locust will still fire whatever events appropriately.
答案2
得分: 0
以下是翻译好的内容:
你可以使用一个单独的 User 类来实现这个。
正如 SocketIOUser 的文档所述,它是:
一个包括 Socket.IO WebSocket 连接的用户。你可以轻松地将它用作普通 WebSocket 的模板,Socket.IO 只是我的使用案例。你可以使用多重继承将其与 HttpUser 结合起来(class MyUser(HttpUser, SocketIOUser))。
所以可以这样:
class MySocketIOUser(HttpUser, SocketIOUser):
@task
def my_task(self):
self.connect("wss://...")
self.client.post(...)
self.send("something")
有关 WebSocket 部分的更多信息,请参阅 https://github.com/SvenskaSpel/locust-plugins/blob/master/examples/socketio_ex.py。
英文:
You can use a single User class for this.
As SocketIOUser’s documentation states, it is:
> A User that includes a socket io websocket connection.
You could easily use this a template for plain WebSockets,
socket.io just happens to be my use case. You can use multiple
inheritance to combine this with an HttpUser
(class MyUser(HttpUser, SocketIOUser)
So something like:
class MySocketIOUser(HttpUser, SocketIOUser):
@task
def my_task(self):
self.connect("wss://...")
self.client.post(...)
self.send("something")
See https://github.com/SvenskaSpel/locust-plugins/blob/master/examples/socketio_ex.py for more about the WebSocket-parts.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论