locust的使用

Locust是什么?

Locust 是一個(gè)開源負(fù)載測試工具。使用 Python 代碼定義用戶行為,也可以仿真百萬個(gè)用戶。
Locust 是非常簡單易用,分布式,用戶負(fù)載測試工具。Locust 主要為網(wǎng)站或者其他系統(tǒng)進(jìn)行負(fù)載測試,能測試出一個(gè)系統(tǒng)可以并發(fā)處理多少用戶。
Locust 是完全基于時(shí)間的,因此單個(gè)機(jī)器支持幾千個(gè)并發(fā)用戶。相比其他許多事件驅(qū)動(dòng)的應(yīng)用,Locust 不使用回調(diào),而是使用輕量級(jí)的處理方式 gevent。

安裝

pip  install  locustio

如果你打算通過多進(jìn)程或多機(jī),分布式地運(yùn)行Locust,我們建議你也安裝pyzmq

pip install pyzmq

TaskSet類

每個(gè)Locust類必須有一個(gè)指向一個(gè)TaskSettask_set屬性。
TaskSet是任務(wù)的集合,這些任務(wù)是普通的python可調(diào)用對(duì)象。
當(dāng)負(fù)載測試啟動(dòng)的時(shí)候,產(chǎn)生的每一個(gè)Locust類的實(shí)例都會(huì)開始執(zhí)行它們的TaskSet。接下來發(fā)生的是,每個(gè)TaskSet會(huì)選擇它的任務(wù)中的一個(gè),并且調(diào)用它。接下來等待min_waitmax_wait毫秒,然后它會(huì)再選擇下一個(gè)要被調(diào)用的任務(wù),再等待,等等。

聲明任務(wù)

為TaskSet聲明任務(wù)最典型的方式是使用task裝飾器。
下面是一個(gè)例子:

def index(l):
    l.client.get("/")

def stats(l):
    l.client.get("/stats/requests")

class UserTasks(TaskSet):
    # one can specify tasks like this
    tasks = [index, stats]
    
    # but it might be convenient to use the @task decorator
    @task(3)
    def task1(self):
        self.client.get("/does_not_exist")

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

class WebsiteUser(HttpLocust):
    """
    Locust user class that does requests to the locust web server running on localhost
    """
    host = "http://127.0.0.1:8089"
    min_wait = 2000
    max_wait = 5000
    task_set = UserTasks
  • @task裝飾器帶一個(gè)可選的weight參數(shù),它用于指定任務(wù)的執(zhí)行比例。在下面的例子中,task2的執(zhí)行次數(shù)是task1的兩倍
  • TaskSet支持嵌套
class MyTaskSet(TaskSet):  
    @task
    class SubTaskSet(TaskSet):
        @task
        def my_task(self):
            pass
  • on_start函數(shù)
    TaskSet類可以定義一個(gè)on_start方法,當(dāng)模擬用戶開始執(zhí)行TaskSet類的時(shí)候,on_start方法會(huì)被調(diào)用。

HttpLocust類

本文已經(jīng)包含了Locust用戶的任務(wù)調(diào)度部分,為了真正的給一個(gè)系統(tǒng)進(jìn)行負(fù)載測試,我們需要生成HTTP請(qǐng)求,HttpLocust類的存在,就是為了解決這個(gè)問題。當(dāng)使用HttpLocust類的時(shí)候,每個(gè)實(shí)例都有一個(gè)client屬性---它是能夠用于生成HTTP請(qǐng)求的HttpSession類的實(shí)例

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
  1. 使用上面的Locust類,每個(gè)模擬用戶在請(qǐng)求之間都會(huì)等待5-15秒,并且/的請(qǐng)求次數(shù)是/about/的兩倍。
  1. 用心的讀者可能會(huì)覺得很奇怪:在TaskSet內(nèi)部我們使用self.client而非self.locust.client開引用HttpSession實(shí)例,我們能這么做是因?yàn)椋?code>TaskSet類有一個(gè)便捷的被稱作client的屬性,它簡單的返回self.locust.client。
  • 生成GET請(qǐng)求的例子
response = self.client.get("/about")  
print "Response status code:", response.status_code  
print "Response content:", response.content  
  • 生成POST請(qǐng)求的例子
response = self.client.post("/login", {"username":"testuser", "password":"secret"})  
  • 人工控制一個(gè)請(qǐng)求被視為成功還是失敗

默認(rèn)情況下,除非HTTP響應(yīng)碼是ok(2xx),否則請(qǐng)求就會(huì)被標(biāo)記為失敗。大多數(shù)情況下,默認(rèn)的情況就是我們想要的。然而有時(shí):比如說你期望返回404,或者是測試一個(gè)即使發(fā)生錯(cuò)誤,仍然返回200 OK的系統(tǒng),就存在人工控制locust將請(qǐng)求視為成功還是失敗的需求。 通過使用catch_response參數(shù)和with語句,可以把一個(gè)響應(yīng)碼是okay的請(qǐng)求標(biāo)記成失敗

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

正如可以把響應(yīng)碼為OK的請(qǐng)求標(biāo)記為失敗,也可以使用catch_response參數(shù)和with語句,將返回http錯(cuò)誤代碼的請(qǐng)求在統(tǒng)計(jì)中報(bào)告為成功。

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

HTTP客戶端被配置成以安全模式運(yùn)行,任何由于連接錯(cuò)誤,超時(shí)之類導(dǎo)致失敗的請(qǐng)求都不會(huì)拋出異常,而是返回一個(gè)空的虛擬的Response對(duì)象,在Locust的統(tǒng)計(jì)中請(qǐng)求會(huì)被報(bào)告為一個(gè)失敗。被返回的虛擬的Response對(duì)象的content屬性被設(shè)置為None,status_code屬性被設(shè)置為0

  • 將到具有動(dòng)態(tài)參數(shù)的URL的請(qǐng)求分組

對(duì)于網(wǎng)站來說,擁有URL中包含某種動(dòng)態(tài)參數(shù)的頁面是非常普遍的。通常在Locust的統(tǒng)計(jì)中,把這些URL分成一組是有意義的??梢酝ㄟ^給HttpSession實(shí)例的請(qǐng)求方法傳遞name參數(shù),來完成這件事。
例子:

# 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]")

啟動(dòng)

  • 如果運(yùn)行的文件名稱為locustfile.py 則可以直接運(yùn)行
locust --host=http://example.com
  • 如果locust file被放到了其他的地方,我們可以運(yùn)行
 locust -f 當(dāng)前文件夾路徑/my_file.py --host=http://example.com
  • 如果需要多線程分布式運(yùn)行l(wèi)ocust,啟動(dòng)的時(shí)候需要指定masterslave
 locust -f 當(dāng)前文件夾路徑/my_file.py --host=http://example.com  --master 

然后我們可以啟動(dòng)任意數(shù)量的slave進(jìn)程:(用master機(jī)器的ip替換192.168.0.14)

locust -f my_locustfile.py --slave --master-host=192.168.0.14

分布式運(yùn)行Locust

參數(shù)

屬性 解釋
-f 文件名
--host 運(yùn)行的接口的host
--master 以master的模式運(yùn)行l(wèi)ocust,web接口會(huì)運(yùn)行在這個(gè)節(jié)點(diǎn)上
--slave 以slave模式運(yùn)行l(wèi)ocust。
--master-host=X.X.X.X --slave一起使用,用來設(shè)置master節(jié)點(diǎn)的ip或主機(jī)名(默認(rèn)是127.0.0.1)
--master-port=5557 --slave一起使用,用來設(shè)置master節(jié)點(diǎn)的端口號(hào)(默認(rèn)是5557),注意locust既會(huì)使用指定的端口號(hào),又會(huì)使用指定的端口號(hào)+1,因此如果設(shè)置為5557,那么locust既會(huì)使用5557,也會(huì)使用5558
--master-bind-host=X.X.X.X --master一起使用,決定master節(jié)點(diǎn)綁定到哪一個(gè)網(wǎng)絡(luò)接口,默認(rèn)是*(所有可用的網(wǎng)絡(luò)接口)

min_wait和max_wait屬性

除了task_set屬性,也可以聲明min_waitmax_wait屬性,它們是一個(gè)模擬用戶在執(zhí)行任務(wù)之間等待的最大和最小時(shí)間,單位是毫秒。min_wait和max_wait默認(rèn)是1000,因此如果沒有聲明min_waitmax_wait,locust在執(zhí)行每個(gè)任務(wù)之間總是會(huì)等待1秒。
使用下面的locustfile,在任務(wù)之間每個(gè)用戶等待5-15秒:

from locust import Locust, TaskSet, task

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

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

參考:
http://timd.cn/2015/09/17/locust/
https://my.oschina.net/u/2306127/blog/482625

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容