Locust小結
背景
目前網上的教程基本都是1.0之前的,locust叢1.0版本就發生了較多的變化,網上的教程基本不可用。目前locust版本是1.1.1,以下的說明都是針對1.1.1來進行的。
locust適用情景
- 需要邏輯判斷但不復雜的請求,並持續化存儲
- 壓測過程要求不嚴格,例如相對復雜的步進式放量
- 已有專門的壓測指標采集方式,locust提供的監控很雞肋
locust新特性
如果你不想知道改動點,可以之間跳過這塊。
1、HttpLocust的更新
舊版本使用的是TaskSet進行任務或者請求編寫,然后在使用HttpLocust進行任務或者請求聲明,以及基礎屬性配置,一般會進行思考時間、host、task_set設置任務類等;
新版本將HttpLocust重寫成User,並且HttpUser繼承於User,所以推薦使用HttpUser進行任務聲明;
另外TaskSet中的task_set已被刪除,如果仍要使用TaskSet,則需要在HttpUser中使用tasks進行存儲,例
# -*- coding: utf-8 -*-
from locust import HttpUser, task, between, TaskSet
# 采用舊版TaskSet進行定義,不推薦使用,需要在User相關類中定義,才可以被調用
# 補充:SequentialTaskSet是TaskSet子類,作用就是忽略權重,完全根據編寫順序來控制任務執行順序,多用於事務壓測
class TestBaiduSearch2(TaskSet):
def on_start(self):
self.header = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
}
self.payload = {
"wd": "selenium",
}
@task
def search(self):
baidu_response = self.client.get(url="/s", params=self.payload, verify=True, headers=self.header)
print(baidu_response.url)
# 新版建議都使用HttpUser進行定義
class TestBaiDuSearch(HttpUser):
host = "https://www.baidu.com" # 設置host,如果腳本僅是在本地運行或者基本不變的,建議直接腳本固定,反之在啟動運行是加入host參數
tasks = [TestBaiduSearch2] # 添加任務
wait_time = between(100, 200) # 設置思考時間范圍
def on_start(self):
self.payload = {
"wd": "locust",
}
self.header = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
}
@task
def search(self):
# 默認采用的requests模塊的session,這塊不做贅述,自行查找
baidu_response = self.client.get(url="/s", params=self.payload, verify=True, headers=self.header)
print(baidu_response.url)
if __name__ == '__main__':
import os
# 啟動腳本,以最大請求5個,每秒步進為1
os.system("locust -f test11.py --headless -u 5 -r 1")
2、任務標記
請求方法進行標志,@tag進行裝飾,在啟動參數時可以進行選擇啟動或者排除
class TestBaiDuSearch(HttpUser):
# 命令行啟動就可使用--tags(-T)和--exclude-tags(-E)指定啟動/排除任務
@task
@tag("https","baidu")
def search(self):
baidu_response = self.client.get(url="/s", params=self.payload, verify=True, headers=self.header)
print(baidu_response.url)
啟動標志為『https』的任務
locust -f test11.py --host https://www.baidu.com --tags https
3、環境變量變量名修改
LOCUST_MASTER -> LOCUST_MODE_MASTER
LOCUST_SLAVE -> LOCUST_MODE_WORKER
LOCUST_MASTER_PORT -> LOCUST_MASTER_NODE_PORT
LOCUST_MASTER_HOST -> LOCUST_MASTER_NODE_HOST
CSVFILEBASE -> LOCUST_CSV
4、其他變動
4.1 從機的命令行參數改變為--worker,--expect-workers
4.2 無Web模式的命令行參數改變為--headless
4.3 鈎子函數統一使用events進行綁定
...
locust使用
簡單介紹
locust是基於python開發的一個協程請求庫,協程又稱微線程,多個協程可以只運行在一個線程中,由開發者自行選擇切換的時機,所以相對於進程、線程擁有更小的資源切換浪費,但由於是運行在python解析器之上的,所以存在GIL鎖進制,另外默認的網絡請求庫還是requests這種同步庫,所以單進程下並發不會太高。如果想用locust進行並發請求,必定要使用分布式+異步請求庫。
安裝
pip install locust 默認安裝最新版本
常用寫法
# -*- coding: utf-8 -*-
from locust import HttpUser, task, between,tag,SequentialTaskSet,events
# 新版建議都使用HttpUser進行定義
class TestBaiDuSearch(HttpUser):
wait_time = between(0.1, 0.2) # 設置請求的思考時間范圍,單位是秒
# weight = 3 任務類權重,越大優先級越高
# tasks =[] 建議少用這個,任務集中控制,非要用大概率是你的設計有問題
# 整體啟動執行
@events.test_start.add_listener
def on_test_start(**kwargs):
print("大王我來了!!!")
# 整體結束執行
@events.test_stop.add_listener
def on_test_stop(**kwargs):
print("大王我走了???")
# 每個請求集啟動之前進行的操作
def on_start(self):
self.payloadPref = {
"wd": "locust",
}
self.payloadAuto = {
"wd": "selenium",
}
self.header = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
}
print("這就開始了?!")
# 每個請求集結束之后進行的操作
def on_stop(self):
print("這就玩完了?!")
# @task 進行任務標志,里面的數字是權重,權重越大,發起的請求占比越高,如下,相同請求量下,兩者比例約3:1
# @tag 進行任務標簽注釋,可以選擇啟動或者排查
@task(3)
@tag("baidu")
def searchPref(self):
baidu_response = self.client.get(url="/s", params=self.payloadPref, verify=True, headers=self.header)
# print(baidu_response.url)
@task(1)
def searchAuto(self):
baidu_response = self.client.get(url="/s", params=self.payloadAuto, verify=True, headers=self.header)
# print(baidu_response.url)
if __name__ == '__main__':
import os
# 啟動腳本,以最大請求5個,每秒步進為1
os.system("locust -f test11.py --host https://www.baidu.com --headless -u 5 -r 1")
由於locust默認采用的是requests中的session進行請求發送,所以同樣是支持post、put、head等請求方式,詳見requests官網
配置化啟動
locust不是僅能通過命令行配置啟動,如果每次都要寫那么長的配置,估計出錯的概率也不低,所以locust也提供了配置化啟動的形式,這個真的方便!!例:
locust --config=配置文件路徑
在腳本同級目錄下編寫配置文件,baidu.conf
# 腳本路徑,目前是在同級目錄就直接寫文件名了
# 具體的參數有什么還是參考官網給出 https://docs.locust.io/en/stable/configuration.html
locustfile = testbaidu.py
headless = true
host = http://www.baidu.com
users = 6
hatch-rate = 2
run-time = 1m
命令行執行
locust --config=baidu.conf
分布式啟動
locust支持一主多從的控制模式,這點也對於單機並發也是一個極大的提升,目前基本都是多核多線程的機器,所以分布式可以充分發揮單機的能力。
推薦單機啟動的從機+主機不超過CPU核數,當然你可以試試
首先啟動master,默認占用8089端口用於web界面,5557用於從機交互
locust -f testbaidu.py --master
接連啟動slave
locust -f testbaidu.py --worker --master-host=127.0.0.1 #此處本地,遠程的話使用對應ip即可
瀏覽器打開 http://127.0.0.1:8089,可見右上角,WORKERS顯示的數量與啟動的從機數量一致。
注意,界面填寫的User量級是總量會均分給每個從機。
locust壓測大殺器
前面也多次講到了locust如果采用了HttpUser,則默認的請求庫是使用requests,requests是同步阻塞的請求庫,對於壓測來說,還是很致命的,每個請求發送完成之后都在響應的回來,即是你機器配置好,也無法充分發揮。
所以locust提供了一個異步請求庫,對於代碼我們只需將HttpUser改為FastHttpUser即可,前提導入
from locust.contrib.fasthttp import FastHttpUser
另注意,FastHttpUser提供的geventhttpclient其實有坑,比如post請求的data就要求只能是String類型,相對於requests請求還是不太好用。
locust的步進模式
用過jmeter的同學應該都知道,壓測一般會采用逐級放量的形式進行請求發送。
同樣locust也提供了這種步進默認。
--step-load 啟用步進模式
--step-users 每級的用戶增量
--step-time 增量間隔
locust -f --headless -u 1000 -r 100 --run-time 30m --step-load --step-users 300 --step-time 1m
無web界面啟動locust,設置總用戶數1000,每秒增量100個用戶,運行總時長30分鍾,啟動步進模式,步進用戶300,維持每個步進模式時間為1分鍾
當達到300用戶時會維持一分鍾,然后在持續增量用戶,達到600在維持一分鍾,以此類推
locust的其他功能
1、自定義請求對象 https://docs.locust.io/en/stable/testing-other-systems.html
2、擴展Web界面 https://docs.locust.io/en/stable/extending-locust.html
3、將locust作為庫來進行使用,調用內部的協程api https://docs.locust.io/en/stable/use-as-lib.html