Tasks和Events是Locust性能測試工具的核心技術,有了它們,Locust才能稱得上是一個性能工具。
Tasks
從上篇文章知道,locustfile裡面必須要有一個類,繼承User類,當性能測試開始後,會産生一個User類執行個體,這就是常說的模拟使用者。這些使用者會選擇task執行,休眠一會,再選擇新的task,不斷疊代。
task是Python中的可調用對象,它是一項任務,對于Web系統來說,可以是登入、查詢、下訂單、支付等等。
@task裝飾器
@task是定義task最簡單直接的方式,比如:
from locust import User, task, constant
class MyUser(User):
wait_time = constant(1)
@task
def my_task(self):
print("User instance (%r) executing my_task" % self)
@task有一個可選參數,用來設定task的選擇權重,比如:
from locust import User, task, between
class MyUser(User):
wait_time = between(5, 15)
@task(3)
def task1(self):
pass
@task(6)
def task2(self):
pass
task2比task1被選擇的可能性大兩倍。
tasks屬性
除了@task裝飾器,還可以設定User類的tasks屬性來定義任務,比如:
from locust import User, constant
def my_task(user):
pass
class MyUser(User):
tasks = [my_task]
wait_time = constant(1)
注意,my_task()函數有一個參數,它是User類的執行個體。
tasks可以是一個清單:
tasks = [my_task1, my_task2, my_task3]
Locust會使用Python中的random.choice()從裡面随機選取。
tasks也可以是一個字典:
{my_task: 3, another_task: 1}
後面的int型鍵值代表的是被選擇權重,這個字典等價于清單:
[my_task, my_task, my_task, another_task]
@tag裝飾器
@tag用來打标記,在運作時選擇哪些task執行,哪些task不執行。比如:
class MyUser(User):
wait_time = constant(1)
@tag('tag1')
@task
def task1(self):
pass
@tag('tag1', 'tag2')
@task
def task2(self):
pass
@tag('tag3')
@task
def task3(self):
pass
@task
def task4(self):
pass
- 如果使用
,那麼隻有task1和task2會被選擇。--tags tag1
- 如果使用
,那麼隻有task2和task3會被選擇。--tags tag2 tag3
- 如果使用
,那麼隻有task1、task2和task4會被選擇。--exclude-tags tag3
注意,exclude的優先級更高,如果某個tag既包括又排除,那麼會被排除。
Events
@task定義了性能測試的執行動作,@events作為補充,定義了測試開始前和測試結束後的處理。
注意,每個模拟使用者開始和結束的處理是使用的User類的on_start()和on_stop()方法。
test_start和test_stop
測試開始前和測試結束後觸發。示例:
from locust import events
@events.test_start.add_listener
def on_test_start(environment, **kwargs):
print("A new test is starting")
@events.test_stop.add_listener
def on_test_stop(environment, **kwargs):
print("A new test is ending")
分布式執行時,它們隻會在master節點生效。
init
init和test_start不同,它會在每個Locust程序開始時觸發,分布式執行時,每個節點(worker程序)都會生效。
from locust import events
from locust.runners import MasterRunner
@events.init.add_listener
def on_locust_init(environment, **kwargs):
if isinstance(environment.runner, MasterRunner):
print("I'm on master node")
else:
print("I'm on a worker or standalone node")
Events是一項hook技術,在學習Locust進階用法時再做進一步介紹。
Locust項目結構
官方建議如下:
common/
__init__.py
auth.py
config.py
locustfile.py
或者
locustfiles/
api.py
website.py
requirements.txt
FastHttpUser
從上篇文章可以知道,HttpUser類比User類更常用,它的client屬性是HttpSession類(requests.Session子類)的一個執行個體,可以使用requests發HTTP請求:
# 使用HttpUser
from locust import HttpUser,task,constant
class MyUser(User):
wait_time = constant(1)
@task
def my_task1(self):
with self.client.get("https://www.baidu.com/", catch_response=True) as res:
if res.status_code == 200:
print("成功")
else:
print("失敗")
但是requests性能是不太好的,如果要産生更高的壓力,建議使用FastHttpUser,性能可以提升5到6倍:
# 使用FastHttpUser
from locust import task, constant
from locust.contrib.fasthttp import FastHttpUser
class MyUser(FastHttpUser):
wait_time = constant(1)
@task
def my_task(self):
with self.client.get("https://www.baidu.com/", catch_response=True) as response:
if response.status_code == 200:
print("成功")
else:
print("失敗")
由于它們的API不一樣,都有各自的适用場景,是以FastHttpUser不能完全替代HttpUser。
小結
本文嚴格來說是上篇文章《locustfile中的User類和HttpUser類》的下篇,介紹了核心技術Tasks和Events,并給出了官方推薦的項目結構,最後介紹了比HttpUser性能更好的FastHttpUser,如果想要更多的并發,可以考慮使用後者。經過這兩篇文章的學習,已經可以開始動手實踐使用Locust進行性能測試了。如果使用locust指令啟動後,無法打開網頁,可以試試加上參數:
locust --web-host="127.0.0.1"
。
參考資料:
https://zhuanlan.zhihu.com/p/118470760
https://docs.locust.io/en/stable/writing-a-locustfile.html#tasks
https://www.axihe.com/tools/locust/increase-performance.html
https://blog.csdn.net/u012002125/article/details/113363768