6000字Locust入門詳解

[TOC]

一弯囊、Locust 性能測(cè)試

同步Notion : https://young-glen.notion.site/Locust-994ec41de38744009814a63822b10eda

問題引言:

  1. 主流性能工具對(duì)比
  2. 為什么要用<font color=red>locust</font>進(jìn)行性能測(cè)試
  3. 如何對(duì)http接口進(jìn)行性能測(cè)試
  4. 如何對(duì)websocket接口進(jìn)行性能測(cè)試
  5. locust性能測(cè)試報(bào)告分析
  6. locust 核心部件了解
  7. 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é)三步:

  1. 創(chuàng)建==locust.HttpUser== 之類
  2. 為待測(cè)試用例添加@locust.task 裝飾器
  3. 使用self.client 發(fā)送請(qǐng)求
  4. 指定 wait_time 屬性

3. 啟動(dòng)測(cè)試

Locust官方文檔(API)解讀(全)

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概念

  1. 父類是個(gè)User 烫葬?

    表示要生成進(jìn)行負(fù)載測(cè)試的系統(tǒng)的 HTTP“用戶”界弧。

    • 性能測(cè)試 模擬真實(shí)用戶
    • 每個(gè)user相當(dāng)于一個(gè)協(xié)程鏈接 ,進(jìn)行相關(guān)系統(tǒng)交互操作
  2. 為什么方法搭综,要包裝為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ǔ)法
  1. 安裝 pip install websocket_client

  2. 使用

    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

    1. 創(chuàng)建專用客戶端鏈接

    2. 設(shè)計(jì)統(tǒng)計(jì)結(jié)果

    3. 設(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á)式

  • task: 任務(wù)(用戶行為)

    • tasks :
      • 用戶類的用戶行為方法上添加@task修飾
      • 引用外部用戶行為方法時(shí) 使用tasks實(shí)現(xiàn)
  • 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è)方法來聲明成功和失敗别厘,分別是successfailure。其中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()

兩步驟:

  1. all_locusts_spawned 創(chuàng)建鉤子函數(shù)
  2. 將locust實(shí)例掛載到監(jiān)聽器 events.spawning_complete.add_listener
  3. 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ī)器)

  1. Step1:→ 啟動(dòng)locust master節(jié)點(diǎn)

    locust -f locustfile07.py --master

  2. Step2:→ 每個(gè)工作節(jié)點(diǎn) locust -f locustfile07.py --worker

多機(jī)主從模式

  1. 選擇其中一臺(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
  1. 其它機(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)核切換的開銷这嚣,可以不加鎖的訪問全局變量鸥昏,所以上下文的切換非常快姐帚。

吏垮、

  1. 進(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)行銷毀

  2. 線程與協(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))

更多查閱:

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í)路線

docs.locust.io

3. WebSocket與HTTP的關(guān)聯(lián)和差異

相同:

  1. 建立在TCP之上椒振,通過TCP協(xié)議來傳輸數(shù)據(jù)昭伸。
  2. 都是可靠性傳輸協(xié)議
  3. 都是應(yīng)用層協(xié)議。

不同:

  1. WebSocket是HTML5中的協(xié)議澎迎,支持持久連接庐杨,HTTP不支持持久連接
  2. HTTP是單向協(xié)議,只能由客戶端發(fā)起夹供,做不到服務(wù)器主動(dòng)向客戶端推送信息

4. 延伸閱讀&知識(shí)庫(kù)

locustio

本文由mdnice多平臺(tái)發(fā)布

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末灵份,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子哮洽,更是在濱河造成了極大的恐慌各吨,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件袁铐,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡横浑,警方通過查閱死者的電腦和手機(jī)剔桨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來徙融,“玉大人洒缀,你說我怎么就攤上這事∑奂剑” “怎么了树绩?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)隐轩。 經(jīng)常有香客問我饺饭,道長(zhǎng),這世上最難降的妖魔是什么职车? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任瘫俊,我火速辦了婚禮鹊杖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘扛芽。我一直安慰自己骂蓖,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布川尖。 她就那樣靜靜地躺著登下,像睡著了一般。 火紅的嫁衣襯著肌膚如雪叮喳。 梳的紋絲不亂的頭發(fā)上被芳,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音嘲更,去河邊找鬼筐钟。 笑死,一個(gè)胖子當(dāng)著我的面吹牛赋朦,可吹牛的內(nèi)容都是我干的篓冲。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼宠哄,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼壹将!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起毛嫉,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤诽俯,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后承粤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體暴区,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年辛臊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了仙粱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡彻舰,死狀恐怖伐割,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情刃唤,我是刑警寧澤隔心,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站尚胞,受9級(jí)特大地震影響硬霍,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜辐真,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一须尚、第九天 我趴在偏房一處隱蔽的房頂上張望崖堤。 院中可真熱鬧,春花似錦耐床、人聲如沸密幔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)胯甩。三九已至,卻和暖如春堪嫂,著一層夾襖步出監(jiān)牢的瞬間偎箫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工皆串, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留淹办,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓恶复,卻偏偏與公主長(zhǎng)得像怜森,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子谤牡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容