[TOC]
一弯囊、Locust 性能測(cè)試
同步Notion : https://young-glen.notion.site/Locust-994ec41de38744009814a63822b10eda
問題引言:
- 主流性能工具對(duì)比
- 為什么要用<font color=red>locust</font>進(jìn)行性能測(cè)試
- 如何對(duì)http接口進(jìn)行性能測(cè)試
- 如何對(duì)websocket接口進(jìn)行性能測(cè)試
- locust性能測(cè)試報(bào)告分析
- locust 核心部件了解
- locust 主要用法詳解
(一). 性能測(cè)試工具
主流性能測(cè)試工具對(duì)比
- loadrunner : 收費(fèi) 昂貴
- jmeter: 開源(二次開發(fā)) 踢故、基于java、多線程 洼专、使用gui設(shè)計(jì)用例 ,xml保存 蠕搜、錄制工具
loadRunner vs Jmeter
loadrunner筆記:https://mp.weixin.qq.com/s/V0wLFxrw4VIp9jTXVEKlag
LoadRunner | Jmeter |
---|---|
非開源工具 | 開源工具 |
C 語(yǔ)言 | 100% java 語(yǔ)言 |
檢查點(diǎn)(web_reg_find) | 斷言 |
關(guān)聯(lián)(web_reg_save_param) | 關(guān)聯(lián)(前置/后置處理器正則提取器) |
支持IP欺騙 | 不支持IP 欺騙 |
測(cè)試結(jié)果分析圖表功能強(qiáng)大(數(shù)據(jù)采集) | 測(cè)試結(jié)果分析圖表功能相對(duì)較弱滔以,需依賴擴(kuò)展插件 |
重量級(jí) | 輕量級(jí) |
安裝復(fù)雜 | 安裝簡(jiǎn)單 |
跨平臺(tái) | |
根據(jù)不同負(fù)載生成不同數(shù)量并發(fā)用戶 | 當(dāng)前一個(gè)線程組只能生成一個(gè) |
性能 | 支持web端功能測(cè)試 |
廣泛支持業(yè)界各種標(biāo)準(zhǔn)協(xié)議、多種平臺(tái)開發(fā)腳本 | 組件 |
認(rèn)識(shí)Locust
定義
Locust是一款易于使用的分布式負(fù)載測(cè)試工具歼捐,完全基于事件何陆,即一個(gè)locust節(jié)點(diǎn)也可以在一個(gè)進(jìn)程中支持?jǐn)?shù)千并發(fā)用戶,不使用回調(diào)豹储,通過gevent使用輕量級(jí)過程(即在自己的進(jìn)程內(nèi)運(yùn)行)贷盲。
locust: 開源 、基于python 剥扣,非多線程(協(xié)程)晃洒、“用例即代碼” 慨灭; 無錄制工具朦乏、
- python的一個(gè)庫(kù) 球及,需要python3.6 及以上環(huán)境支持
- 可用做性能測(cè)試
- 基于事件,用協(xié)程 進(jìn)行性能測(cè)試
- 支持 圖形 呻疹、no-gui吃引、 分布式等多種運(yùn)行方式
為什么選擇locust
基于協(xié)程 ,低成本實(shí)現(xiàn)更多并發(fā)
腳本增強(qiáng)(“測(cè)試即代碼”)
使用了requests發(fā)送http請(qǐng)求
支持分布式
使用Flask 提供WebUI
有第三方插件、 易于擴(kuò)展
(二) locust 基本用法
約定大于配置
1.安裝locust
pip install locust
locust -v
2.編寫用例
test_xxx (一般測(cè)試框架約定)
dockerfile (docker約定)
locustfile.py (locust約定)
# locustfile.py
eg: 入門示例
from locust import HttpUser, task, between
# User ?
# function 包裝task
class MyHttpUser(HttpUser):
wait_time = between(1, 2) # 執(zhí)行任務(wù) 等待時(shí)長(zhǎng) 檢查點(diǎn) 思考時(shí)間
@task
def index_page(self):
self.client.get("https://baidu.com/123")
self.client.get("https://baidu.com/456")
pass
總結(jié)三步:
- 創(chuàng)建==locust.HttpUser== 之類
- 為待測(cè)試用例添加@locust.task 裝飾器
- 使用self.client 發(fā)送請(qǐng)求
- 指定 wait_time 屬性
3. 啟動(dòng)測(cè)試
GUI 模式啟動(dòng) locust
啟動(dòng)locust
訪問:*http://[::1]:8089/*
指標(biāo)詳解:
- Number of users 模擬用戶數(shù)
- Spawn rate : 生產(chǎn)數(shù) (每秒)刽锤、 =>jmeter : Ramp-Up Period (in seconds)
- Host (e.g. http://www.example.com) => 取決腳本中 絕對(duì)地址
- ![](https://s3.bmp.ovh/imgs/2022/06/14/22e82961a5609f42.png)
-
WebUI 模塊說明:
- New test:點(diǎn)擊該按鈕可對(duì)模擬的總虛擬用戶數(shù)和每秒啟動(dòng)的虛擬用戶數(shù)進(jìn)行編輯镊尺;
- Statistics:類似于jmeter中Listen的聚合報(bào)告;
- Charts:測(cè)試結(jié)果變化趨勢(shì)的曲線展示圖并思,分別為每秒完成的請(qǐng)求數(shù)(RPS)庐氮、響應(yīng)時(shí)間、不同時(shí)間的虛擬用戶數(shù)宋彼;
- Failures:失敗請(qǐng)求的展示界面弄砍;
- Exceptions:異常請(qǐng)求的展示界面;
- Download Data:測(cè)試數(shù)據(jù)下載模塊输涕, 提供三種類型的CSV格式的下載音婶,分別是:Statistics、responsetime莱坎、exceptions衣式;
命令行模式啟動(dòng) locust
locust -f locustfile.py --headless -u 500 -r 10 --host 123 -t 1h5m
框架是通過命令`locust`運(yùn)行的,常用參數(shù)有:
- -H:指定測(cè)試的主機(jī)地址(注:會(huì)覆蓋Locust類指定的主機(jī)地址)
- -f:指定測(cè)試腳本地址(注:腳本中必須包含一個(gè)Locust的衍生類)
- --no-web:不啟動(dòng)web網(wǎng)頁(yè)檐什,而是直接開始運(yùn)行測(cè)試碴卧,需提供屬性-c和-r
- -u:并發(fā)的用戶數(shù),與--no-web一起使用
- -r:每秒啟動(dòng)的用戶數(shù)乃正,與--no-web一起使用
- -t:運(yùn)行時(shí)間(單位:秒)住册,與--no-web一起使用
- -L:日志級(jí)別,默認(rèn)為INFO
調(diào)試命令:locust -f **.py --no-web -u 1 -t 1
運(yùn)行命令:locust -f **.py
4. locust概念
-
父類是個(gè)User 烫葬?
表示要生成進(jìn)行負(fù)載測(cè)試的系統(tǒng)的 HTTP“用戶”界弧。
- 性能測(cè)試 模擬真實(shí)用戶
- 每個(gè)user相當(dāng)于一個(gè)協(xié)程鏈接 ,進(jìn)行相關(guān)系統(tǒng)交互操作
-
為什么方法搭综,要包裝為task
-
task 表示用戶要進(jìn)行的操作
- 訪問首頁(yè) → 登錄 → 增垢箕、刪改查 → homPage
TaskSet : 定義用戶將執(zhí)行的一組任務(wù)的類。測(cè)試任務(wù)開始后兑巾,每個(gè)Locust用戶會(huì)從TaskSet中隨機(jī)挑選 一個(gè)任務(wù)執(zhí)行
-
具體的內(nèi)容: 方法的代碼
class MyHttpUser(HttpUser): #用戶 # wait_time = lambda self: random.expovariate(1)*1000 wait_time = between(1, 2) # 執(zhí)行任務(wù) 等待時(shí)長(zhǎng) 檢查點(diǎn) 思考時(shí)間 @task def index_page(self): # 用戶執(zhí)行操作 self.client.get("https://baidu.com/123") #服務(wù)錯(cuò)誤条获、網(wǎng)絡(luò)錯(cuò)誤 self.client.get("https://baidu.com/456") # 斷言 、 業(yè)務(wù)錯(cuò)誤
-
(三) locust 自定義壓測(cè)協(xié)議 websocket
<span style="color:#ff0000;">locust 并非 http 接口測(cè)試工具 蒋歌, 只是內(nèi)置了 “HttpUser”</span> 示例 帅掘,可以測(cè)試任何協(xié)議: websocket 委煤、socket 、mqtt (webAPP修档、Hybrid碧绞、Html5 、桌面瀏覽器) 吱窝、rpc
什么是websocket協(xié)議 讥邻?
WebSocket是一種在單個(gè)TCP連接上進(jìn)行全雙工通信的協(xié)議。 WebSocket使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡(jiǎn)單院峡,允許服務(wù)端主動(dòng)向客戶端推送數(shù)據(jù)兴使。在WebSocket API中,瀏覽器和服務(wù)器只需要完成一次握手照激,兩者之間就直接可以創(chuàng)建持久性的連接发魄,并進(jìn)行雙向數(shù)據(jù)傳輸。ws長(zhǎng)連接俩垃、 和http有本質(zhì)不同 ;
客戶端發(fā)起励幼,服務(wù)器可能接受或拒絕切換到新協(xié)議∵赫客戶端可使用常用的協(xié)議(如HTTP / 1.1)發(fā)起請(qǐng)求赏淌,請(qǐng)求說明需要切換到HTTP / 2或甚至到WebSocket
<span style="background:#FFFFBB;"> 一句話概述:協(xié)議“使用HTTP進(jìn)行握手, 后使用TCP進(jìn)行會(huì)話” 的全雙工協(xié)議
</span>
選擇websocket 客戶端
目前pypi , 2個(gè)ws庫(kù)
- websockets: 提供client 啄清, 提供了server 六水; 使用async 語(yǔ)法
- websocket_client: 僅提供client 、使用(非async)同步語(yǔ)法
安裝
pip install websocket_client
-
使用
import asyncio import websockets async def hello(): async with websockets.connect('ws://localhost:8765') as websocket: name = input("What's your name? ") await websocket.send(name) print(f" send:>>> {name}") greeting = await websocket.recv() print(f" recv: <<< {greeting}") asyncio.get_event_loop().run_until_complete(hello())
創(chuàng)建WebSocketUser
創(chuàng)建專用客戶端鏈接
設(shè)計(jì)統(tǒng)計(jì)結(jié)果
-
設(shè)定成功辣卒、失敗條件
pyfile:
TimeoutError(10060, '[WinError 10060] 由于連接方在一段時(shí)間后沒有正確答復(fù)或連接的主機(jī)沒有反應(yīng)掷贾,連接嘗試失敗。') 1.請(qǐng)求服務(wù)器的反爬機(jī)制導(dǎo)致的荣茫,請(qǐng)求不被接受的 ; ip限制
→ 網(wǎng)頁(yè)訪問驗(yàn)證 -2. http的連接數(shù)超過最大限制想帅。</br>headers的Connection參數(shù)默認(rèn)為keep-alive,之前所有請(qǐng)求的鏈接都一直存在啡莉,占用了后續(xù)的鏈接請(qǐng)求 3. 網(wǎng)站服務(wù)器太差 → 修改中間件配置(SLB港准、nginx 、ApiGateway 熔斷咧欣、限流 ~ </br> →timeout 超時(shí)時(shí)間 </br> ........... 9大策略和6大指標(biāo) 浅缸、 ........... 硬件(計(jì)算機(jī)體系機(jī)構(gòu))、操作系統(tǒng)(OS\JVM)魄咕、文件系統(tǒng)衩椒、網(wǎng)絡(luò)通信、數(shù)據(jù)庫(kù)系統(tǒng)、中間件(transaction毛萌、message苟弛、app)、應(yīng)用程序本身
本地:
netsh winsock reset
→ 重啟
初步結(jié)果:
1. RPS xxxx 左右
2. 最大用戶數(shù) xxx
> 表示:當(dāng)前允許最大用戶數(shù)請(qǐng)求阁将,但是無法全部返回結(jié)果
<span style="background:#BBFFBB;">常見錯(cuò)誤</span> | <span style="color:#0070c0;">可能分析原因</span> |
---|---|
TPS波動(dòng)較大 | 網(wǎng)絡(luò)波動(dòng)膏秫、其他服務(wù)資源競(jìng)爭(zhēng)以及垃圾回收問題 |
高并發(fā)下大量報(bào)錯(cuò) | 短連接導(dǎo)致的端口被完全占用以及線程池最大線程數(shù)配置較小及超時(shí)時(shí)間較短導(dǎo)致。 |
集群類系統(tǒng)冀痕,各服務(wù)節(jié)點(diǎn)負(fù)載不均衡 | SLB服務(wù)設(shè)置了會(huì)話保持 |
并發(fā)數(shù)不斷增加荔睹,TPS上不去,CPU使用率較低 | SQL沒有創(chuàng)建索引/SQL語(yǔ)句篩選條件不明確言蛇、代碼中設(shè)有同步鎖,高并發(fā)時(shí)出現(xiàn)鎖等待宵距; |
connection reset腊尚、服務(wù)重啟、timeout等 | 參數(shù)配置满哪、服務(wù)策略婿斥、阻塞及各種鎖導(dǎo)致 |
(四). locust 核心組件
核心組件: 2類 ,4個(gè)
-
User : 在locust中User類表示一個(gè)用戶哨鸭。locust將為每一個(gè)被模擬的用戶生成一個(gè)User類實(shí)例民宿,而我們可以在User類中定義一些常見的屬性來定義用戶的行為。
- HttpUser
-
Task: 用戶行為
- SequentialTaskSet
- TaskSet:
- tasks屬性將多個(gè)TaskSet子類嵌套在一起
- 類中相互嵌套
- User類中嵌入TaskSet類像鸡,作為User的子類
Events : locust提供的事件鉤子活鹰,用于一些再運(yùn)行過程中執(zhí)行特定時(shí)間的操作。
重要的屬性:
-
wait_time
三種時(shí)間間隔表達(dá)式
固定時(shí)間只估, 由constant(wait)函數(shù)提供
區(qū)間隨機(jī)時(shí)間: `between(min_wait, max_wait)函數(shù)
自適應(yīng)節(jié)奏時(shí)間:
constant_pacing
用于確保任務(wù)每 X 秒(最多)運(yùn)行一次
-
task: 任務(wù)(用戶行為)
- tasks :
- 用戶類的用戶行為方法上添加@task修飾
- 引用外部用戶行為方法時(shí) 使用tasks實(shí)現(xiàn)
- tasks :
-
weight
測(cè)試中志群,存在多個(gè)User Class,默認(rèn)情況下locust將為每個(gè)User Class的實(shí)例的數(shù)量是相同的蛔钙。通過設(shè)置weight屬性锌云,來控制locust為我們的User Class生成不同數(shù)量的實(shí)例。
- locustfile07.py
(五). locust 擴(kuò)展增強(qiáng)
→ Python代碼
1. 錄制用例
不支持 吁脱, →插件增強(qiáng)
2. 數(shù)據(jù)關(guān)聯(lián)
locustfile05.py
使用變量方式進(jìn)行傳遞
3. 參數(shù)化
locustfile09.py
locust參數(shù)化:引入隊(duì)列的概念 queue 桑涎,實(shí)現(xiàn)方式是將參數(shù)推入隊(duì)列,測(cè)試時(shí)依次取出兼贡,全部取完后 locust 會(huì)自動(dòng)停止攻冷。若是使用參數(shù)循環(huán)壓測(cè),需要將取出的參數(shù)再推入隊(duì)尾紧显。
- 變量
- CSV
- 隊(duì)列
- 讲衫。。
4. 檢查點(diǎn)
locust默認(rèn)情況下會(huì)使用默認(rèn)的檢查點(diǎn),比如當(dāng)接口超時(shí)涉兽、鏈接失敗等原因是招驴,會(huì)自動(dòng)判斷失敗
原理:
- 使用self.client提供的catch_response=True`參數(shù), 添加locust提供的ResponseContextManager類的上下文方法手動(dòng)設(shè)置檢查點(diǎn)枷畏。
- ResponseContextManager里面的有兩個(gè)方法來聲明成功和失敗别厘,分別是
success
和failure
。其中failure方法需要我們傳入一個(gè)參數(shù)拥诡,內(nèi)容就是失敗的原因触趴。
locustfile10.py
from requests import codes
from locust import HttpUser, task, between
class DemoTest(HttpUser):
host = 'https://www.baidu.com'
wait_time = between(2, 15)
def on_start(self):
# 通過手動(dòng)傳入catch_response=True 參數(shù)手動(dòng)設(shè)置檢查點(diǎn)
with self.client.get('/', catch_response=True) as r:
if r.status_code == codes.bad:
r.success()
else:
r.failure("請(qǐng)求百度首頁(yè)失敗了哦哦")
@task
def search_locust(self):
with self.client.get('/s?ie=utf-8&wd=locust', catch_response=True) as r:
if r.status_code == codes.ok:
r.success()
else:
r.failure("搜索locust失敗了哦哦")
5. 思考時(shí)間
- wait_time
- between
- constant
6. 權(quán)重
- 第一種:方法上指定
locust默認(rèn)是隨機(jī)執(zhí)行taskset里面的task的。
權(quán)重通過在@task參數(shù)中設(shè)置渴肉,如代碼中hello:world:item是1:3:2冗懦,實(shí)際執(zhí)行時(shí)的代碼,在user中tasks會(huì)將任務(wù)生成列表[hello,world,world,world,item,item]
@tag 裝飾器 :# locust -f locustfile06.py --tags tag1
task不止一個(gè)時(shí)仇祭,可以通過@tag給task打標(biāo)簽進(jìn)行分類披蕉,在執(zhí)行測(cè)試時(shí),通過--tags name執(zhí)行指定帶標(biāo)簽的task
# locustfile06.py
import time
from locust import HttpUser, task, between, TaskSet, tag
class QuickstartUser(TaskSet):
wait_time = between(1, 5)
# wait_time = constant(3) #固定時(shí)間
@task
def hello_world(self):
self.client.get("/hello")
self.client.get("/world")
@tag("tag1", "tag2")
@task(3)
def view_items(self):
for item_id in range(10):
#self.client.request_name="/item?id=[item_id]"#分組請(qǐng)求
# 將統(tǒng)計(jì)的10條信息分組到名為/item條目下
self.client.get(f"/item?id={item_id}", name="/item")
time.sleep(1)
def on_start(self):
self.client.post("/login", json={"username": "foo", "password": "bar"})
class MyUserGroup(HttpUser):
""" 定義線程組 """
tasks = [QuickstartUser] # tasks 任務(wù)列表
host = "http://www.baidu.com"
-
第二種:在屬性中指定
文件中存在多個(gè)用戶類場(chǎng)景乌奇,
- 命令行上沒有指定用戶類没讲,Locust 將生成相同數(shù)量的每個(gè)用戶類。
- 可以通過將它們作為命令行參數(shù)傳遞來指定要使用同一 locustfile 中的哪些用戶類:
locust -f locustfile07.py QuickstartUser2
# locustfile07.py
import time
from locust import HttpUser, task, between, TaskSet, tag, constant
class QuickstartUser1(HttpUser):
host = "http://www.baidu.com"
wait_time = constant(4)
weight = 3 #屬性中指定
@task
def hello_world(self):
self.client.get("/hello1")
self.client.get("/world1")
def on_start(self):
self.client.post("/login1", json={"username": "foo", "password": "bar"})
class QuickstartUser2(HttpUser):
host = "http://www.baidu.com"
wait_time = between(1, 5)
weight = 1
@task
def hello_world(self):
self.client.get("/hello2")
self.client.get("/world2")
def on_start(self):
self.client.post("/login2", json={"username": "foo", "password": "bar"})
7. 集合點(diǎn)
什么是集合點(diǎn)礁苗?
集合點(diǎn)用以同步虛擬用戶爬凑,以便恰好在同一時(shí)刻執(zhí)行任務(wù)。在[測(cè)試計(jì)劃]中试伙,可能會(huì)要求系統(tǒng)能夠承受1000 人同時(shí)提交數(shù)據(jù)嘁信,可以通過在提交數(shù)據(jù)操作前面加入集合點(diǎn),這樣當(dāng)虛擬用戶運(yùn)行到提交數(shù)據(jù)的集合點(diǎn)時(shí)迁霎,就檢查同時(shí)有多少用戶運(yùn)行到集合點(diǎn)吱抚,如果不到1000 人,已經(jīng)到集合點(diǎn)的用戶在此等待考廉,當(dāng)在集合點(diǎn)等待的用戶達(dá)到1000 人時(shí)秘豹,1000 人同時(shí)去提交數(shù)據(jù),從而達(dá)到測(cè)試計(jì)劃中的需求昌粤。
注意:框架本身沒有直接封裝集合點(diǎn)的概念 既绕,間接通過gevent并發(fā)機(jī)制,使用gevent的鎖來實(shí)現(xiàn)
semaphore是一個(gè)內(nèi)置的計(jì)數(shù)器:
每當(dāng)調(diào)用acquire()時(shí)涮坐,內(nèi)置計(jì)數(shù)器-1
每當(dāng)調(diào)用release()時(shí)凄贩,內(nèi)置計(jì)數(shù)器+1
計(jì)數(shù)器不能小于0,當(dāng)計(jì)數(shù)器為0時(shí)袱讹,acquire()將阻塞線程直到其他線程調(diào)用release()
兩步驟:
- all_locusts_spawned 創(chuàng)建鉤子函數(shù)
- 將locust實(shí)例掛載到監(jiān)聽器 events.spawning_complete.add_listener
- Locust實(shí)例準(zhǔn)備完成時(shí)觸發(fā)
示例代碼:
# locustfile08.py
import os
from locust import HttpUser, TaskSet, task,between,events
from gevent._semaphore import Semaphore
all_locusts_spawned = Semaphore()
all_locusts_spawned.acquire()# 阻塞線程
def on_hatch_complete(**kwargs):
"""
Select_task類的鉤子方法
:param kwargs:
:return:
"""
all_locusts_spawned.release() # # 創(chuàng)建鉤子方法
events.spawning_complete.add_listener(on_hatch_complete) #掛在到locust鉤子函數(shù)(所有的Locust示例產(chǎn)生完成時(shí)觸發(fā))
n = 0
class UserBehavior(TaskSet):
def login(self):
global n
n += 1
print("%s個(gè)虛擬用戶開始啟動(dòng)疲扎,并登錄"%n)
def logout(self):
print("退出登錄")
def on_start(self):
self.login()
all_locusts_spawned.wait() # 同步鎖等待
@task(4)
def test1(self):
url = '/list'
param = {
"limit":8,
"offset":0,
}
with self.client.get(url,params=param,headers={},catch_response = True) as response:
print("用戶瀏覽登錄首頁(yè)")
@task(6)
def test2(self):
url = '/detail'
param = {
'id':1
}
with self.client.get(url,params=param,headers={},catch_response = True) as response:
print("用戶同時(shí)執(zhí)行查詢")
@task(1)
def test3(self):
"""
用戶查看查詢結(jié)果
:return:
"""
url = '/order'
param = {
"limit":8,
"offset":0,
}
with self.client.get(url,params=param,headers={},catch_response = True) as response:
print("用戶查看查詢結(jié)果")
def on_stop(self):
self.logout()
class WebsiteUser(HttpUser):
host = 'http://www.baidu.com'
tasks = [UserBehavior]
wait_time = between(1, 2)
if __name__ == '__main__':
os.system("locust -f locustfile08.py")
8. 分布式
Locust 通過協(xié)程實(shí)現(xiàn)單機(jī)大量并發(fā)昵时,但對(duì)多核 CPU 的支持并不好,可通過在一臺(tái)機(jī)器上啟動(dòng)多個(gè) Locust 實(shí)例實(shí)現(xiàn)對(duì)多核 CPU 的利用(<span style="color:#7030a0;">單機(jī)分布式</span>) 椒丧,同理:?jiǎn)闻_(tái)計(jì)算機(jī)不足以模擬所需的用戶數(shù)量壹甥,Locust 也支持在多臺(tái)計(jì)算機(jī)上進(jìn)行分布式負(fù)載測(cè)試。
一種是單機(jī)設(shè)置master和slave模式壶熏,另外一種是有多個(gè)機(jī)器句柠,其中一個(gè)機(jī)器設(shè)置master,其它機(jī)器設(shè)置slave節(jié)點(diǎn)
注意:主節(jié)點(diǎn)master計(jì)算機(jī)和每個(gè)work工作節(jié)點(diǎn)計(jì)算機(jī)都必須具有 Locust 測(cè)試腳本的副本棒假。
單機(jī)主從模式
其中 slave 的節(jié)點(diǎn)數(shù)要小于等于本機(jī)的處理器數(shù)
步驟: 以單臺(tái)計(jì)算機(jī)為例(既當(dāng)做主控機(jī)溯职,也當(dāng)做工作機(jī)器)
-
Step1:→ 啟動(dòng)locust master節(jié)點(diǎn)
locust -f locustfile07.py --master
Step2:→ 每個(gè)工作節(jié)點(diǎn) locust -f locustfile07.py --worker
多機(jī)主從模式
- 選擇其中一臺(tái)電腦,啟動(dòng)master節(jié)點(diǎn)帽哑,因?yàn)橹鞴?jié)點(diǎn)無法操作別的節(jié)點(diǎn)谜酒,所以必須在其它機(jī)器上啟動(dòng)從屬Locust節(jié)點(diǎn),后面跟上--worker參數(shù)祝拯,以及 --master-host(指定主節(jié)點(diǎn)的IP /主機(jī)名)甚带。
locust -f locustfile07.py --master
- 其它機(jī)器上(環(huán)境和主節(jié)點(diǎn)環(huán)境一致,都需要有l(wèi)ocust的運(yùn)行環(huán)境和腳本),啟動(dòng) slave 節(jié)點(diǎn)佳头,設(shè)置 --master-host
locust -f locustfile.py --worker --master-host=192.168.x.xx
更多參數(shù)介紹
- --master
將 locust 設(shè)置為 master 模式。Web 界面將在此節(jié)點(diǎn)上運(yùn)行晴氨。
- --worker
將locuster設(shè)置為worker模式康嘉。
- --master-host= X. X. X. X
可選擇與-- worker一起使用,以設(shè)置主節(jié)點(diǎn)的主機(jī)名/IP (默認(rèn)值為127.0.0.1)
- --master-port
可選地與-- worker一起用于設(shè)置主節(jié)點(diǎn)的端口號(hào)(默認(rèn)值為5557)籽前。
- -master-bind-host= X. X. X. X
可選擇與--master一起使用亭珍。 確定主節(jié)點(diǎn)將綁定到的網(wǎng)絡(luò)接口。 默認(rèn)為*(所有可用接口)枝哄。
- --master-bind-port=5557
可選擇 與--master一起使用肄梨。 確定主節(jié)點(diǎn)將偵聽的網(wǎng)絡(luò)端口。 默認(rèn)值為5557挠锥。 - --expect-workers= X
在使用--headless啟動(dòng)主節(jié)點(diǎn)時(shí)使用众羡。 然后主節(jié)點(diǎn)將等待,直到 X worker節(jié)點(diǎn)已經(jīng)連接蓖租,然后測(cè)試才開始粱侣。
9. 資源監(jiān)控
10. docker 運(yùn)行l(wèi)ocust
拉取鏡像:
docker pull locustio/locust
運(yùn)行容器:
docker run -p 8089:8089 -v $PWD:/mnt/locust locustio/locust -f /mnt/locust/locustfile.py
Docker Compose:
version: '3'
services:
master:
image: locustio/locust
ports:
- "8089:8089"
volumes:
- ./:/mnt/locust
command: -f /mnt/locust/locustfile.py --master -H http://master:8089
worker:
image: locustio/locust
volumes:
- ./:/mnt/locust
command: -f /mnt/locust/locustfile.py --worker --master-host master
11. 高性能 FastHttpUser
Locust 的默認(rèn) HTTP 客戶端使用python-requests。如果您計(jì)劃以非常高的吞吐量運(yùn)行測(cè)試并且運(yùn)行 Locust 的硬件有限蓖宦,那么它有時(shí)效率不夠齐婴。Locust 還附帶FastHttpUser
使用geventhttpclient代替。它提供了一個(gè)非常相似的 API稠茂,并且使用的 CPU 時(shí)間顯著減少柠偶,有時(shí)將給定硬件上每秒的最大請(qǐng)求數(shù)增加了 5 到 6 倍。
<span style="background:#ffbbff;">在相同的并發(fā)條件下使用FastHttpUser能有效減少對(duì)負(fù)載機(jī)的資源消耗從而達(dá)到更大的http請(qǐng)求。
</span>
<span style="background:#ffbbff;">
</span>
比對(duì)結(jié)果如下:
locustfile11.py
HttpUser:
對(duì)比:FastHttpUser
(六)附外
0. 進(jìn)程诱担、線程毡证、協(xié)程區(qū)別
進(jìn)程:進(jìn)程是具有一定獨(dú)<span style="color:#ff0000;">立功能的程序關(guān)于某個(gè)數(shù)據(jù)集合上的一次運(yùn)行活動(dòng)</span>,進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個(gè)獨(dú)立單位。每個(gè)<span style="color:#ff0000;">進(jìn)程都有自己的獨(dú)立內(nèi)存空間</span>该肴,不同進(jìn)程通過<span style="color:#ff0000;">進(jìn)程間通信</span>來通信情竹。由于進(jìn)程比較重量,占據(jù)獨(dú)立的內(nèi)存匀哄,所以上下文進(jìn)程間的切換開銷(棧秦效、寄存器、虛擬內(nèi)存涎嚼、文件句柄等)比較大阱州,但相對(duì)比較穩(wěn)定安全。
線程: 線程是進(jìn)程的一個(gè)實(shí)體,是<span style="color:#ff0000;">CPU調(diào)度和分派的基本單位</span>,它是比進(jìn)程更小的能獨(dú)立運(yùn)行的基本單位.線程自己基本上不擁有系統(tǒng)資源,只擁有一點(diǎn)在運(yùn)行中必不可少的資源(如程序計(jì)數(shù)器,一組寄存器和棧),但是它可與同屬一個(gè)進(jìn)程的其他的線程共享進(jìn)程所擁有的全部資源法梯。線程間通信主要通過共<span style="color:#ff0000;">享內(nèi)存苔货,上下文切換很快,資源開銷較少</span>立哑,但相比進(jìn)程不夠穩(wěn)定容易丟失數(shù)據(jù)夜惭。
協(xié)程: 協(xié)程是一種用戶態(tài)的輕量級(jí)線程,<span style="color:#c00000;">協(xié)程的調(diào)度完全由用戶控制</span>铛绰。協(xié)程擁有自己的寄存器上下文和棧诈茧。協(xié)程調(diào)度切換時(shí),將寄存器上下文和棧保存到其他地方捂掰,在切回來的時(shí)候敢会,恢復(fù)先前保存的寄存器上下文和棧,直接操作棧則基本沒有內(nèi)核切換的開銷这嚣,可以不加鎖的訪問全局變量鸥昏,所以上下文的切換非常快姐帚。
吏垮、
-
進(jìn)程與線程比較:
進(jìn)程用于獨(dú)立的地址空間 ;線程依附于進(jìn)程(先有進(jìn)程后有線程) 卧土,可以共享進(jìn)程的地址空間
進(jìn)程之間不共享全局變量 惫皱, 線程之間共享全局變量
線程是cpu 調(diào)度的基本單位; 進(jìn)程是操作系統(tǒng)分配資源資源的最小單位
進(jìn)程之間相互獨(dú)立 尤莺,都可并發(fā)執(zhí)行 (核數(shù)大于線程數(shù))
多進(jìn)程運(yùn)行其中某個(gè)進(jìn)程掛掉不會(huì)影響其他進(jìn)程運(yùn)行, 多線程開發(fā)中當(dāng)前進(jìn)程掛掉 依附于當(dāng)前進(jìn)程中的多線程進(jìn)行銷毀
-
線程與協(xié)程比較
一個(gè)線程可包含多個(gè)協(xié)程 旅敷,一個(gè)進(jìn)程也可單獨(dú)擁有多個(gè)協(xié)程
線程、進(jìn)程 同步機(jī)制 颤霎,協(xié)程異步
協(xié)程保留最近一次調(diào)用時(shí)狀態(tài)媳谁,每次過程重入相當(dāng)于喚醒
線程的切換由操作系統(tǒng)負(fù)責(zé)調(diào)度涂滴,協(xié)程由用戶自己進(jìn)行調(diào)度
資源消耗:線程的默認(rèn)Stack大小是1M,而協(xié)程更輕量晴音,接近1K柔纵。
線程: 輕量級(jí)的進(jìn)程 協(xié)程: 輕量級(jí)的線程 (用戶態(tài))
更多查閱:
- 一文讀懂什么是進(jìn)程、線程锤躁、協(xié)程
- Processes, threads, and coroutines
- Comparison of Process , Thread and Coroutines
1. 更多命令
如果Locust文件位于與locustfile.py在不同的子目錄/或者文件名不一樣搁料,則使用參數(shù)-f+文件名:
$ locust -f locust_files/my_locust_file.py
要在多個(gè)進(jìn)程中運(yùn)行Locust,我們可以通過指定--master:
$ locust -f locust_files/my_locust_file.py --master
啟動(dòng)任意數(shù)量的從屬進(jìn)程:
$ locust -f locust_files/my_locust_file.py --slave
如果要在多臺(tái)機(jī)器上運(yùn)行Locust系羞,則在啟動(dòng)從屬服務(wù)器時(shí)還必須指定主服務(wù)器主機(jī)(在單臺(tái)計(jì)算機(jī)上運(yùn)行Locust時(shí)不需要郭计,因?yàn)橹鞣?wù)器主機(jī)默認(rèn)為127.0.0.1):
$ locust -f locust_files/my_locust_file.py --slave --master-host=192.168.0.100
還可以在配置文件(locust.conf或~/.locust.conf)或以LOCUST_前綴的env vars中設(shè)置參數(shù)
例如:(這將與上一個(gè)命令執(zhí)行相同的操作)
$ LOCUST_MASTER_HOST=192.168.0.100 locust
注意:要查看所有可用選項(xiàng),請(qǐng)鍵入:locust —help
2. 學(xué)習(xí)路線
3. WebSocket與HTTP的關(guān)聯(lián)和差異
相同:
- 建立在TCP之上椒振,通過TCP協(xié)議來傳輸數(shù)據(jù)昭伸。
- 都是可靠性傳輸協(xié)議
- 都是應(yīng)用層協(xié)議。
不同:
- WebSocket是HTML5中的協(xié)議澎迎,支持持久連接庐杨,HTTP不支持持久連接
- HTTP是單向協(xié)議,只能由客戶端發(fā)起夹供,做不到服務(wù)器主動(dòng)向客戶端推送信息
4. 延伸閱讀&知識(shí)庫(kù)
本文由mdnice多平臺(tái)發(fā)布