Locust代碼實戰
- 1. 引言
- 2. Locust實體展示
- 2.1 官網代碼示例
- 2.2 Locust 代碼模板及執行順序
- 3. Locust 類代碼分析
- 3.1 實體代碼展示
- 3.2 classTaskSet 用法及展示
- 3.2.1 定義
- 3.2.2 代碼展示
- 4. Locust高級用法
- 4.1 關聯
- 4.2 引數化
- 4.2.1 聊一聊引數化
- 4.2.2 三個場景認識引數化
- 4.3 檢查點
- 5. Locust運行模式
- 5.1 單行程運行模式
- 5.1.1 定義及決議
- 5.1.2 有Web UI模式
- 5.1.3 無Web UI模式
- 5.1.4 啟動locust
- 5.2 多行程分布式運行
- 5.2.1 master啟動
- 5.2.2 slave 啟動
- 6. Locust 結果分析
1. 引言
在本章節,你可以學習到:
1、Locust代碼實體展示及解讀:
①官網代碼示例
②demo模板代碼
3、Loucst的高級用法:
①關聯
②引數化
③檢查點
4、Locust的運行模式:
①單行程運行模式
②多行程分布式運行
5、Locust界面展示及結果分析
2. Locust實體展示
2.1 官網代碼示例
我們來看看官網的第一個例子,
很簡單:
# -*- coding: utf-8 -*-
"""
@ auth : carl_DJ
@ time : 2020-9-23
"""
from locust import HttpUser, between, task
class WebsiteUser(HttpUser):
#設定等待時間間隔
wait_time = between(5, 15)
def on_start(self):
self.client.post("/login", {
"username": "test_user",
"password": ""
})
@task
def index(self):
self.client.get("/")
self.client.get("/static/assets.js")
@task
def about(self):
self.client.get("/about/")
這里有幾點說一下:
1、between: 設定等待時間, 5s~15s;
2、client.get/ client.post: 用法跟request是一樣的,
其他的就沒有什么可以重點強調的!
2.2 Locust 代碼模板及執行順序
這段代碼,小魚展示兩點:
1、locust demo模板;
2、locust 代碼執行順序,
# -*- coding: utf-8 -*-
"""
@ auth : carl_DJ
@ time : 2020-9-23
"""
from locust import HttpUser,TaskSet,task
'''
執行順序:
Locust setup → TaskSet setup → TaskSet on_start →
TaskSet tasks → TaskSet on_stop → TaskSet teardown →
Locust teardown
'''
class UserBehavor(TaskSet):
#啟動locust是運行setup方法
def setup(self):
print('task setup')
def teardown(self):
print('task teardown')
#虛擬用戶啟動task時運行
def on_start(self):
print('start')
#虛擬用戶結束task時運行
def on_stop(self):
print('end')
@task(2)
def index(self):
self.client.get('/')
@task(1)
def profile(self):
self.client.get('/profile')
class WebsitUser(HttpUser):
def setup(self):
print('locust setup')
def teardown(self):
print('locust teardown')
host = 'http://xxx.com'
task_set = task(UserBehavor)
min_wait = 100
max_wait = 5000
if __name__ == '__main__':
pass
雖然小魚展示了模板,可以直接使用,但是,里面的內容,需要各位大佬自己填充~~
畢竟 業務不同,填充的內容也不一樣!!
小屌絲:魚哥,感覺你在開車,但是沒證據!!
小魚:都快一點了,你還不睡覺,白富美不香嗎!!!
小屌絲:…
3. Locust 類代碼分析
3.1 實體代碼展示
關于locust類的詳細講解,放在了第一章節,因為
小魚覺得:先了解基礎,再去看代碼,這樣就不至于看代碼想看天書,至少遇到一個類,能有一個印象,
這里,為了方便大家,點擊下方帶顏色的文字即可進入第一章節:
《深聊性能測驗,從入門到放棄之:Locust性能自動化(一)初識Locust》
回歸正題,老規矩,先上代碼,再逐層分析
# -*- coding: utf-8 -*-
"""
@ auth : carl_DJ
@ time : 2020-9-23
"""
from locust import HttpUser,task,TaskSet
'''
在版本10.1,已經不再使用HttpLocust 和Locust,
取而代之的是HttpUser 和User
'''
# 定義ScriptTasks類,繼承TaskSet類
class ScriptTasks(TaskSet):
#初始化,每個locust用戶開始做的第一件事
def on_start(self):
#放置 用戶名和密碼
self.client.post('/login', {
"username":"carl_dj",
"password":'111111'
})
#@task()裝飾的方法為一個事務,方法的引數用于指定該行為的執行權重,引數越大每次被虛擬用戶執行的概率越高,默認為1
@task(2)
#創建index方法,
def index(self):
self.client.get('/')
@task(1)
def about(self):
#self.client 屬性使用python的request庫的方法,呼叫和使用方法和request一樣
self.client.get('/about')
@task(2)
def demo(self):
payload = {}
headers = {}
self.client.post('/demo', data = payload,headers = headers)
#TaskSet類,該類定義用戶任務資訊(模擬用戶資訊),
class WebsitUser(HttpUser):
#指向一個定義的用戶行為
task_set = task(ScriptTasks)
#被測系統的host,
host = 'http://www.xxxxxx.com'
#每個用戶執行兩個任務間隔時間最小值,單位是(毫秒,默認是1000ms)
min_wait = 100
# 每個用戶執行兩個任務間隔時間最大值,單位是(毫秒)
max_wait = 5000
這里小魚在強調一次:
1、關于 HttpUser 和User的使用, 在版本10.1之后,就需要換成HttpUser 和 User,否則報錯;
>>>因為小魚發現,很多網站的大佬都在使用HttpLocust 和Locust,如果你的Locust 版本是 9.x或者8.x,可以使用,不做強要求,
3.2 classTaskSet 用法及展示
3.2.1 定義
1、TaskSet類實作了虛擬用戶所執行任務的調度演算法,包括:
①規劃任務執行順序:schedule_task;
②挑選下一個任務:execute_next_task;
③執行任務:execute_task;
④休眠等待:wait;
⑤中斷控制:interrupt;
2、在1的基礎上,就可以在TaskSet子類中進行以下操作:
①描述虛擬用戶的業務測驗場景;
②對虛擬用戶的所有行為進行組織和描述;
③對不同任務的權重進行配置;
3、 @task
①通過@task()裝飾的方法為一個事務,
>>>引數越大每次被虛擬用戶執行的概率越高,默認是1,
4、TaskSet子類中采用2種方式定義任務資訊:
① @task
② tasks屬性
3.2.2 代碼展示
1、采用@task裝飾器定義任務資訊:
# -*- coding: utf-8 -*-
"""
@ auth : carl_DJ
@ time : 2020-9-23
"""
from locust import task,TaskSet
class UserBehav(TaskSet):
@task(2)
def test_case1(self):
self.client.get("/testcase1")
@task(4)
def test_case2(self):
self.client.get("/testcase2")
2、采用tasks屬性定義任務資訊:
# -*- coding: utf-8 -*-
"""
@ auth : carl_DJ
@ time : 2020-9-23
"""
from locust import TaskSet
def test_case1(self):
self.client.get("/testcase1")
def test_case2(self):
self.client.get("/testcase2")
class UserBehav(TaskSet):
tasks = {test_case1:2,test_case2:4}
#另一種寫法
# tasks = [(test_job1,1), (test_job1,3)]
上面的代碼,沒有什么難度,這里就不做解釋,
4. Locust高級用法
4.1 關聯
做過介面或者爬蟲的的大佬都知道,傳參是必不可少的,
而常見的場景有session_id,
對于回傳的html頁面,可用采用lxml庫來定位獲取需要的引數,
我們先上代碼
# -*- coding: utf-8 -*-
"""
@ auth : carl_DJ
@ time : 2020-9-23
"""
from locust import HttpUser,task,TaskSet
from lxml import etree
class WebsitTasks(TaskSet):
#獲取session
def get_session(self,html):
tags = etree.HTML(html)
return tags.xpath("輸入標簽需要定位的到元素")
#啟動
def on_start(self):
html = self.client.get('/index')
session = self.get_session(html.text)
#設定payload引數
payload = {
'username': 'carl_dj',
'password':'111111',
'session':session
}
#設定header引數
header = {"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36"}
self.client.post('/login',data = payload,headers = header)
@task(5)
def index(self):
self.client.get('/')
@task(1)
def about(self):
self.client.about('/about/')
class WebsiteUser(HttpUser):
# 被測系統的host,在終端中啟動locust時沒有指定--host引數時才會用到
host = "http://www.xxx.com/user/login"
# TaskSet類,該類定義用戶任務資訊,必填,這里就是:WebsiteTasks類名,因為該類繼承TaskSet;
task_set = task(WebsiteTasks)
# 每個用戶執行兩個任務間隔時間的上下限(毫秒),具體數值在上下限中隨機取值,若不指定默認間隔時間固定為1秒
min_wait = 5000
max_wait = 15000
嗯,詳細的內容都在代碼中標注,這里就不再重新嘮叨,
4.2 引數化
4.2.1 聊一聊引數化
老話說的好:代碼寫死一時爽,框架重構火葬場
雖然大部分大佬還沒有涉及到 設計框架的階段,但是,只要稍微努努力…
火葬場 遲早都是要去滴~ ~
所以,就有了另一句老話:動態代碼一時爽,一直動態一時爽
可見,引數化的作用,真的,很Nice!
話說回來,引數化的作用是啥呢:回圈取資料,資料可重復使用,
4.2.2 三個場景認識引數化
場景1:
>> 模擬3個用戶并發請求網頁,共有100個URL地址,每個虛擬用戶都會依次回圈加載100個URL地址
代碼展示:
# -*- coding: utf-8 -*-
"""
@ auth : carl_DJ
@ time : 2020-9-23
"""
from locust import TaskSet, task, HttpUser
class UserBehav(TaskSet):
def on_start(self):
self.index = 0
@task
def test_visit(self):
url = self.locust.share_data[self.index]
print('visit url: %s' % url)
self.index = (self.index + 1) % len(self.locust.share_data)
self.client.get(url)
class WebsiteUser( HttpUser):
host = 'http://www.xxx.com'
task_set = task(UserBehav)
share_data = ['url1', 'url2', 'url3', 'url4', 'url5']
min_wait = 1000
max_wait = 15000
場景2
>>>模擬3用戶并發注冊賬號,共有9個賬號,要求注冊賬號不重復,注冊完畢后結束測驗
概括:
保證并發測驗資料唯一性,不回圈取資料
>>>所有并發虛擬用戶共享同一份測驗資料,并且保證虛擬用戶使用的資料不重復;
代碼
采用佇列
# -*- coding: utf-8 -*-
"""
@ auth : carl_DJ
@ time : 2020-9-23
"""
from locust import TaskSet, task, HttpUser
import queue
class UserBehav(TaskSet):
@task
def test_register(self):
try:
data = self.locust.user_data_queue.get()
except queue.Empty:
print('account data run out, test ended.')
exit(0)
print('register with user: {}, pwd: {}'\
.format(data['username'], data['password']))
payload = {
'username': data['username'],
'password': data['password']
}
self.client.post('/register', data=payload)
class WebsiteUser(HttpUser):
host = 'http://www.xxx.com'
task_set = task(UserBehav)
user_data_queue = queue.Queue()
for index in range(100):
data = {
"username": "test%04d" % index,
"password": "pwd%04d" % index,
"email": "test%04d@debugtalk.test" % index,
"phone": "186%08d" % index,
}
user_data_queue.put_nowait(data)
min_wait = 1000
max_wait = 15000
場景3
>>>模擬3個用戶并發登錄賬號,總共有9個賬號,要求并發登錄賬號不相同,但資料可回圈使用;
概括:
保證并發測驗資料唯一性,回圈取資料;
>>>所有并發虛擬用戶共享同一份測驗資料,保證并發虛擬用戶使用的資料不重復,并且資料可回圈重復使用,
代碼展示
# -*- coding: utf-8 -*-
"""
@ auth : carl_DJ
@ time : 2020-9-23
"""
from locust import TaskSet, task, HttpUser
import queue
class UserBehav(TaskSet):
@task
def test_register(self):
try:
data = self.locust.user_data_queue.get()
except queue.Empty:
print('account data run out, test ended')
exit(0)
print('register with user: {0}, pwd: {1}' .format(data['username'], data['password']))
payload = {
'username': data['username'],
'password': data['password']
}
self.client.post('/register', data=payload)
self.locust.user_data_queue.put_nowait(data)
class WebsiteUser(HttpUser):
host = 'http://www.xxx.com'
task_set = task(UserBehav)
user_data_queue = queue.Queue()
for index in range(100):
data = {
"username": "test%04d" % index,
"password": "pwd%04d" % index,
"email": "test%04d@debugtalk.test" % index,
"phone": "186%08d" % index,
}
user_data_queue.put_nowait(data)
min_wait = 1000
max_wait = 15000
4.3 檢查點
我們直接使用assert來進行斷言操作,
上代碼:
# -*- coding: utf-8 -*-
"""
@ auth : carl_DJ
@ time : 2020-9-23
"""
from locust import task
@task
def test_interface(self):
#直接使用csdn的某一個api
with self.client.get("https://editor.csdn.net/md?articleId=108596407",name = 'fileconfig',catch_response=True) as response:
#python斷言對介面回傳值中的max欄位進行斷言
assert response.json()['rating']['max']==100
#對http回應碼是否200進行判斷
if response.status_code ==200:
response.success()
else:
response.failure("Failed!")
這里說明一下:
1、斷言形式:with self.client.get(“url地址”,catch_response=True) as response;
2、response.status_code獲取http回應碼進行判斷,失敗后會加到統計錯誤表中;
>>>如果直接使用python自帶assert,則不會進入到locust報表,
3、默認不寫引數catch_response=False斷言無效,將catch_response=True才生效,
5. Locust運行模式
運行Locust時,通常會使用到兩種運行模式:單行程運行和多行程分布式運行,
5.1 單行程運行模式
5.1.1 定義及決議
1、Locust所有的虛擬并發用戶均運行在單個Python行程中,
由于單行程的原因,并不能完全發揮壓力機所有處理器的能力,因此主要用于除錯腳本和小并發壓測的情況,
2、當并發壓力要求較高時,就需要用到Locust的多行程分布式運行模式,
>>> 一旦單臺計算機不足以模擬所需的用戶數量,Locust就會支持運行分布在多臺計算機上的負載測驗,
3、多行程分布運行情況:
①多臺壓力機同時運行,每臺壓力機分擔負載一部分的壓力生成;
②同一臺壓力機上開啟多個slave的情況,
>>>如果一臺壓力機有N個處理器內核,那么就在這臺壓力機上啟動一個master,N個slave,
>>>也可以啟動N的倍數個slave,
5.1.2 有Web UI模式
Locust默認采用8089埠啟動web;如果要使用其它埠,就可以使用如下引數進行指定,
引數說明:
① -P, --port:指定web埠,默認為8089.
終端中—>進入到代碼目錄: locust -f locustfile.py --host = xxxxx.com
② -f: 指定性能測驗腳本檔案
③ -host: 被測驗應用的URL地址【如果不填寫,讀取繼承(HttpLocust)類中定義的host】
注意
1、如果Locust運行在本機,在瀏覽器中訪問http://localhost:8089即可進入Locust的Web管理頁面;
2、如果Locust運行在其它機器上,那么在瀏覽器中訪問http://locust_machine_ip:8089即可,
5.1.3 無Web UI模式
如果采用no_web形式,則需使用–no-web引數,并會用到如下幾個引數,
引數說明:
① -c, --clients:指定并發用戶數;
② -n, --num-request:指定總執行測驗次數;
③ -r, --hatch-rate:指定并發加壓速率,默認值位1,
示例展示:
$ locust -f locustfile.py --host = xxxxx --no-web -c 1 -n 2
5.1.4 啟動locust
在Pycharm的 的Terminal 中啟動 locust,
輸入內容:
locust --host =http://localhost -f test_load.py

也可以在 VScode、WindowsPowserShell中啟動,這里我就是用 Pycharm演示一下
5.2 多行程分布式運行
不管是單機多行程,還是多機負載模式,運行方式都是一樣的,都是先運行一個master,再啟動多個slave,
5.2.1 master啟動
1、啟動master時,需要使用–master引數
2、如果要使用8089以外的埠,還需要使用-P, --port引數
示例展示:
locust -f prof_load.py --master --port=8089
5.2.2 slave 啟動
1、啟動slave時需要使用–slave引數
2、在slave中,就不需要再指定埠
3、master啟動后,還需要啟動slave才能執行測驗任務
示例展示
locust -f monitorAgent.py --slave
ocust -f monitorAgent.py --slave --master-host=<locust_machine_ip>
master和slave都啟動完成,就可以進入到Locust 的web界面,剩下的操作,就是界面操作了~
6. Locust 結果分析

Number of users to simulate: 設定虛擬用戶數,對應中no_web模式的-c, --clients引數;
Hatch rate(users spawned/second): 每秒產生(啟動)的虛擬用戶數 , 對應著no_web模式的-r, --hatch-rate引數,默認為1,

上圖:啟動了一個 master 和兩個 slave,由兩個 slave 來向被測驗系統發送請求
性能測驗引數
Type: 請求的型別,例如GET/POST,
Name:請求的路徑,這里為百度首頁,即:https://www.baidu.com/
request:當前請求的數量,
fails:當前請求失敗的數量,
Median:中間值,單位毫秒,一半的服務器回應時間低于該值,而另一半高于該值,
Average:平均值,單位毫秒,所有請求的平均回應時間,
Min:請求的最小服務器回應時間,單位毫秒,
Max:請求的最大服務器回應時間,單位毫秒,
Content Size:單個請求的大小,單位位元組,
reqs/sec:是每秒鐘請求的個數,
相比于LoadRunner,Locust的結果展示十分簡單,主要就四個指標:并發數、RPS、回應時間、例外率,但對于大多數場景來說,這幾個指標已經足夠了,

上圖是 曲線分析圖,
關于locust的代碼實戰及結果分析,就先到這里,
在這里,小魚再多說一句:
萬行代碼從頭寫,先看基礎挺要緊
所以,要弄懂代碼,還是先看基礎,
點擊傳送《深聊性能測驗,從入門到放棄之:Locust性能自動化(一)初識Locust》
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/123922.html
標籤:其他
上一篇:Python編程 基礎練習(四)
