編寫一個Locust文件

Locust文件就是一般的Python文件。唯一的需求就是它至少需要一個繼承于Locust的類.

Locust類

Locust類代表一個用戶(如果愿意忌愚,也可以是一個準(zhǔn)備出動的蝗蟲)舔涎。Locust會為每一個模擬用戶生成一個locust類實(shí)例秒拔。同時會有一些locust類屬性被定義顽素。

task_set屬性

task_set屬性是指向一個定義用戶行為的TaskSet類础倍,下面會有詳細(xì)的介紹烛占。

min_waitmax_wait屬性

除了task_set屬性,另外一個經(jīng)常被使用的就是min_waitmax_wait屬性。是用于各自以毫秒為單位的最小值和最大值忆家,一個模擬用戶將會在每個任務(wù)執(zhí)行時的等待執(zhí)行的時間間隔犹菇。min_waitmax_wait默認(rèn)設(shè)置為1000,如果不聲明的話芽卿,Locust會默認(rèn)在每個任務(wù)間等待1秒揭芍。

參考下面的代碼,每個用戶將會在每個任務(wù)間等待5至15秒:

from locust import Locust, TaskSet, task_set

class MyTaskSet(TaskSet):
    @task
    def my_task(self):
        print "executing my_task"

class MyLocust(Locust):
    task_set = MyTaskSet
    min_wait = 5000
    max_wait = 15000

min_waitmax_wait屬性可以用于重寫TaskSet類卸例。

weight屬性

你可以通過同一個文件來運(yùn)行兩個locust称杨,就像這樣:

locust -f locust_file.py WebUserLocust MobileUserLocust

如果你更傾向于用這種方法來運(yùn)行,便可以在這些類中嘗試weight屬性筷转。比如姑原,就像這樣來定義web用戶比Mobile用戶多3倍

class WebUserLocust(Locust):
    weight = 3
    ...

class MobileUserLocust(Locust):
    weight = 1
    ...

host屬性

host屬性是到要加載目標(biāo)URL的前綴(如:"http://google.com")。通常情況下呜舒,當(dāng)Locust被啟動時锭汛,在命令行中是需要通過--host來指定的。如果host屬性在locustfile文件中被聲明袭蝗,則在命令行中則不需要使用--host屬性來再次聲明店乐。

TaskSet

如果Locust類代表一只準(zhǔn)備出動的蝗蟲,那么你可以說TaskSet類代表蝗蟲的大腦呻袭。每一個Locust類中必須要包含一個指向TaskSettask_set屬性設(shè)置。

TaskSet就像它的名字一樣腺兴,是一個任務(wù)集合左电。這些任務(wù)是常規(guī)的Python調(diào)用,如果我們壓力測試一個拍賣網(wǎng)站,便可以做這些操作加載啟動頁面页响、搜索一些產(chǎn)品篓足、競標(biāo)

當(dāng)一個壓力測試被啟動時闰蚕,每一個準(zhǔn)備的Locust類實(shí)例將會開始執(zhí)行它們的TaskSet栈拖。接下來是每一個TaskSet找到它的task并調(diào)用它。它將在min_waitmax_wait屬性值之間隨機(jī)等待幾毫秒(除非min_waitmax_wait被定義在TaskSet中没陡,在這種情況下將會使用TaskSet設(shè)置的值)涩哟。然后,它將會找到一個新task并調(diào)用盼玄,再次等待贴彼,一直這樣持續(xù)下去。

聲明task

對于TaskSet來說埃儿,典型的聲明task的方法是直接使用task器仗。

參考這個例子:

from locust import Locust, TaskSet, task
class MyTaskSet(TaskSet):
    @task
    def my_task(self):
        print "Locust instance (%r) executing my_task" % (self.locust)

class MyLocust(Locust):
    task_set = MyTaskSet

@task 將會獲取一個可選的權(quán)重參數(shù),用于說明任務(wù)執(zhí)行的比率。在下面的例子中 task2 將會比 task1 執(zhí)行的次數(shù)多兩倍:

from locust import Locust, TaskSet, task
class MyTaskSet(TaskSet):
    min_wait = 5000
    max_wait = 15000

    @task(3)
    def task1(self):
        pass

    @task(6)
    def task2(self):
        password

class MyLocust(Locust):
    task_set = MyTaskSet

task屬性

使用@task操作符來聲明task是一種便捷的方法精钮,并且經(jīng)常是最好的方式威鹿。然而,也可以定義TaskSet中的task通過設(shè)置tasks屬性(使用操作符@task比tasks屬性更流行)轨香。

tasks 屬性不是python列表的調(diào)用就是一個<callbale:int>字典忽你。tasks是python調(diào)用接收執(zhí)行task的TaskSet類實(shí)例參數(shù)。下面是一個極其簡單的示例(不會影響任何測試):

from locust import Locust, TaskSet

def my_task(l):
    pass

class MyTaskSet(TaskSet):
    tasks = [my_task]

class MyLocust(Locust):
    task_set = MyTaskSet

如果task屬性被定義在列表中弹沽,每次任務(wù)被執(zhí)行時檀夹,將會隨機(jī)tasks 屬性中選擇。如果 tasks 是一個帶有關(guān)健字和數(shù)值調(diào)用的字典策橘,被執(zhí)行的任務(wù)將會被隨機(jī)選擇以數(shù)字的比率來執(zhí)行炸渡。就像下面的這樣:

{my_task: 3, another_task:1}

my_task 將會比 another_task 多執(zhí)行三倍。

TaskSet可以嵌套

TaskSet有一個重要的屬性就是可以被嵌套丽已,由于真實(shí)的網(wǎng)站是有一定的業(yè)務(wù)層級結(jié)構(gòu)的蚌堵,并帶有一些子模塊。嵌套的TaskSet將會幫助我們來定義更加真實(shí)的用戶行為沛婴。比如吼畏,我們可以定義TaskSet像下面的結(jié)構(gòu)

  • Main user behaviour
    • Index page
    • Forum page
      • Read thread
        • Reply
      • New thread
      • View next page
    • Browser categories
      • Watch movies
      • Filter movies
    • About page

嵌套TaskSet的方法就像使用task屬性來說明task一樣,但代替參考Python函數(shù)嘁灯,你可以參考下面的TaskSet:

class ForumPage(TaskSet):
    @task(20)
    def read_thread(self):
        pass

    @task(1)
    def new_thread(self):
        pass

    @task(5)
    def stop(self):
        self.interrupt()

class UserBehaviour(TaskSet):
    tasks = {ForumPage:10}

    @task
    def index(self):
        pass

在上面的示例中泻蚊,當(dāng)UserBehaviour的TaskSet執(zhí)行時,F(xiàn)orumPage會被選中來執(zhí)行丑婿,接下來ForumPage的TaskSet將會開始執(zhí)行性雄。ForumPage的TaskSet會找到它的tasks并執(zhí)行它,再等待羹奉,一直這樣持續(xù)下去秒旋。

針對上面的例子中有一個重要的事情要注意,就是在ForumPage頁面中的Stop方法中調(diào)用self.interrupt()诀拭。這個做的事情是停止執(zhí)行ForumPage任務(wù)并在UserBehaviour實(shí)例中繼續(xù)執(zhí)行迁筛。如果在ForumPage中,我們沒有調(diào)用interrupt()方法耕挨,除非被調(diào)用否則Locust不會調(diào)用ForumPage任務(wù)细卧。但通過interrupt函數(shù) ,我們可以結(jié)合weight任務(wù)來定義模擬用戶離開Forum.

也可以在類內(nèi)部聲明嵌套TaskSet,通過使用@task操作符筒占,像聲明正常的task一樣:

class MyTaskSet(TaskSet):
    @task
    class SubTaskSet(TaskSet):
        @task
        def my_task(self):
            pass

on_start函數(shù)

TaskSet可以選擇聲明on_start函數(shù)酒甸。如果這樣的話,當(dāng)模擬用戶開始執(zhí)行TaskSet類時赋铝,函數(shù)被調(diào)用插勤。

關(guān)聯(lián)Locust實(shí)例,或父TaskSet實(shí)例

TaskSet實(shí)例有locust屬性來指向它的Locust實(shí)例,屬性parent用來指向它的父TaskSet(它會指向Locsut實(shí)例农尖,在基類TaskSet中)析恋。

HTTP請求

到現(xiàn)在為止,我們僅覆蓋了一個Locsut用戶的部分任務(wù)計(jì)劃盛卡。為了真實(shí)的壓力測試一個系統(tǒng)時助隧,我們需要生成HTTP請求。為了幫助我們實(shí)現(xiàn)這個功能滑沧,可以使用HttpLocust類并村。當(dāng)使用這個類時,每一個實(shí)例將會獲得一個用于生成Http請求的HttpSession實(shí)例的client屬性滓技。

class HttpLocust

表示一個用于壓力測試的孵化和攻擊系統(tǒng)的HTTP 用戶哩牍。

這個用戶的行為通過task_set屬性來定義,直接指向TaskSet類令漂。

這個類創(chuàng)建一個client屬性膝昆,在初始化時,HTTP客戶端支持為每一個用戶在請求間保存session叠必。

   client=None

HttpSession實(shí)例在Locust初始化時被創(chuàng)建荚孵。client支持cookies,同時在請求間會保存session纬朝。

當(dāng)從HttpLocust類繼承時收叶,我們可以使用client屬性來對服務(wù)器生成HTTP請求。下面是一個locust文件示例用于在一個網(wǎng)站的兩個URL //about/ 共苛。

from locust import HttpLocust, TaskSet, task

class MyTaskSet(TaskSet):
    @task(2)
    def index(self):
        self.client.get('/')

    @task(1)
    def about(self):
        self.client.get('/about/')
class MyLocust(HttpLocust):
    task_set = MyTaskSet
    min_wait = 5000
    max_wait = 15000

使用上面的Locust類判没,每一個模擬用戶將間隔5-15秒內(nèi)請求,并且/將會比/about/請求數(shù)量多2倍俄讹。

細(xì)心的讀者會發(fā)現(xiàn)有一些奇怪,我們使用self.client關(guān)聯(lián)HttpSession實(shí)例绕德,而不是TaskSet,也不是self.locust.client患膛。我們可以這樣做,是因?yàn)?code>TaskSet類有一個屬性調(diào)用client簡單的返回self.locust.client耻蛇。

使用HTTP client

每一個HttpLocust實(shí)例在client屬性中有一個HttpSession實(shí)例踪蹬。HttpSession類實(shí)際上是requests.Session的子類,可使用get post put delete head patchoptions方法來生成HTTP請求臣咖,用于Locust的數(shù)據(jù)統(tǒng)計(jì)跃捣。HttpSession實(shí)例在請求間維護(hù)cookies,因此可用于登錄網(wǎng)站并保存session在請求之間夺蛇。client可以通過Locust實(shí)例的TaskSet實(shí)例來關(guān)聯(lián)疚漆,因此很容易獲取client并在任務(wù)中生成HTTP請求。

下面是一個生成GET請求到 /about 路徑的示例(在這里,我們可以假設(shè) self 是一個TaskSetHttpLocust 類的實(shí)例):

response = self.client.get("/about")
print "Response staus code:", response.status_code
print "Response content:", response.content

下面是一個生成POST請求的示例:

response = self.client.post("/login", {"username": "testuser", "password": "password"})

安全模式

HTTP client被配制運(yùn)行在safe_mode娶聘。這樣做是任何請求在連接超時闻镶、錯誤、相似失敗時將不會拋出異常丸升,而是返回一個空的假Response對象铆农。請求將會在Locust統(tǒng)計(jì)中算做一次失敗。返回假Response內(nèi)容屬性將會被設(shè)置為None狡耻,并且它的status_code將會是0.

手動設(shè)置請求是成功或失敗

默認(rèn)情況下墩剖,請求被標(biāo)記為失敗除非在返回狀態(tài)碼是OK(2XX)。大部分時間內(nèi)夷狰,這個默認(rèn)就是你所需要的岭皂。然而,比如在測試一個URL節(jié)點(diǎn)孵淘,你期待返回狀態(tài)碼為404蒲障,或者測試一個即使錯誤發(fā)生也會返回200的系統(tǒng),因此瘫证,需要手工控制locust來判斷是成功還是失敗揉阎。

一個可以生成失敗請求,即使當(dāng)響應(yīng)代碼是OK背捌,通過使用catch_response參數(shù)和with語法:

with client.get("/", catch_response = True) as response:
    if response.content != "Success":
        response.failure("Got wrong response")

就像一個可以使用響應(yīng)為OK的請求當(dāng)做失敗來處理毙籽,一個方法就是可以使用catch_response參數(shù)和with語法來讓請求HTTP錯誤時,仍然統(tǒng)計(jì)數(shù)據(jù)為成功:

with client.get("/does_not_exist/", catch_response = True) as response:
    if response.status_code = 404:
        response.success()

使用動態(tài)參數(shù)來分組URL請求

針對網(wǎng)站毡庆,有一個常用的功能是獲取URL中包含一些動態(tài)參數(shù)的頁面數(shù)據(jù)坑赡。通常情況下,在Locust統(tǒng)計(jì)中么抗,使用動態(tài)分組在URL中是很有意義的毅否。通過name參數(shù)來給HttpSession傳遞不同的請求方法。

比如:

# Statistics for these requests will be grouped under: /blog/?id=[id]
for i in range(10):
  client.get("/blog?id=%i" % i, name = "/blog?id=[id]")

常用庫

通常蝇刀,大家想分享多個locust文件用于分享常用的庫螟加。在這種情況下,定義項(xiàng)目根目錄用于調(diào)用Locsut是很重要的吞琐,建議將所有的locust文件有些話在項(xiàng)目的根目錄中捆探。

一個平鋪的結(jié)構(gòu)像下面這樣:

  • 項(xiàng)目根目錄
    • commonlib_conf.py
    • commonlib_auth.py
    • locustfile_web_app.py
    • locsutfile_api.py
    • locustfile_ecommerce.py

locust文件可以調(diào)用常用的庫通過使用import commonlib_auth.然而,這種方法不會從locust文件中站粟,清晰分辨出常用庫黍图。

子文件夾可以有一個清晰的方法(查看下面的示例),但是locust僅會有運(yùn)行l(wèi)ocsut文件的位置引用相關(guān)的模塊奴烙。如果你想從你的根目錄導(dǎo)入(如助被,你運(yùn)行l(wèi)ocust命令的位置)剖张,確保在任何locust文件中添加常用庫前有代碼sys.path.append(os.getcwd()),會生成導(dǎo)入根目錄(如恰起,當(dāng)前工作目錄)修械。

  • project root
    • __init__.py
    • common/
      • __init__.py
      • config.py
      • auth.py
    • locustfiles/
      • __init__.py
      • web_app.py
      • api.py
      • ecommerce.py

使用上面的項(xiàng)目結(jié)構(gòu),你的locust文件可以通過下面代碼導(dǎo)入常用的庫:

sys.path.append(os.getcwd())
import common.auth
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末检盼,一起剝皮案震驚了整個濱河市肯污,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌吨枉,老刑警劉巖蹦渣,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異貌亭,居然都是意外死亡柬唯,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門圃庭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锄奢,“玉大人,你說我怎么就攤上這事剧腻【醒耄” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵书在,是天一觀的道長灰伟。 經(jīng)常有香客問我,道長儒旬,這世上最難降的妖魔是什么栏账? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮栈源,結(jié)果婚禮上挡爵,老公的妹妹穿的比我還像新娘。我一直安慰自己甚垦,他們只是感情好茶鹃,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著制轰,像睡著了一般前计。 火紅的嫁衣襯著肌膚如雪胞谭。 梳的紋絲不亂的頭發(fā)上垃杖,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機(jī)與錄音丈屹,去河邊找鬼调俘。 笑死伶棒,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的彩库。 我是一名探鬼主播肤无,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼骇钦!你這毒婦竟也來了宛渐?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤眯搭,失蹤者是張志新(化名)和其女友劉穎窥翩,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鳞仙,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡寇蚊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了棍好。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片仗岸。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖借笙,靈堂內(nèi)的尸體忽然破棺而出扒怖,到底是詐尸還是另有隱情,我是刑警寧澤提澎,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布姚垃,位于F島的核電站,受9級特大地震影響盼忌,放射性物質(zhì)發(fā)生泄漏积糯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一谦纱、第九天 我趴在偏房一處隱蔽的房頂上張望看成。 院中可真熱鬧,春花似錦跨嘉、人聲如沸川慌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽梦重。三九已至,卻和暖如春亮瓷,著一層夾襖步出監(jiān)牢的瞬間琴拧,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工嘱支, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蚓胸,地道東北人挣饥。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像沛膳,于是被迫代替她去往敵國和親扔枫。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理锹安,服務(wù)發(fā)現(xiàn)短荐,斷路器,智...
    卡卡羅2017閱讀 134,659評論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法叹哭,類相關(guān)的語法搓侄,內(nèi)部類的語法,繼承相關(guān)的語法话速,異常的語法讶踪,線程的語...
    子非魚_t_閱讀 31,639評論 18 399
  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說閱讀 10,985評論 6 13
  • Locust是什么? Locust 是一個開源負(fù)載測試工具泊交。使用 Python 代碼定義用戶行為乳讥,也可以仿真百萬個...
    zychen143閱讀 7,149評論 1 2
  • 原文地址:RESTful web API文檔生成器 問:開發(fā)業(yè)務(wù)模塊代碼最重要的是什么?答:API接口文檔 如果你...
    brucewar閱讀 4,888評論 0 51