性能測試Locust--(10)延伸擴展及Locust API--0.14.4

Locust延伸擴展

Locust附帶了很多事件,這些事件提供了以不同方式擴展Locust的鉤子(hooks )。

事件監聽器可以在模塊級註冊到Locust文件中。這裏有一個例子:

from locust import events

def my_success_handler(request_type, name, response_time, response_length, **kw):
    print "Successfully fetched: %s" % (name)

events.request_success += my_success_handler

注意:
強烈建議你在偵聽器中添加通配符關鍵字參數(上面代碼中的** kw),以防止在以後的版本中添加新參數時代碼崩潰。
要查看所有可用事件,請參閱事件[掛鉤](https://docs.locust.io/en/stable/api.html#events)。

添加網絡路由

Locust使用Flask來提供Web UI,因此很容易將Web端點添加到Web UI。只需將Flask應用程序導入您的locustfile並設置一條新路徑:

from locust import web

@web.app.route("/added_page")
def my_added_page():
    return "Another page"

現在應該能夠啓動locust並瀏覽到:http://127.0.0.1:8089/added_page

Locust日誌記錄

Locust附帶有基本的日誌記錄配置,該配置可以選擇使用--loglevel和/或--logfile來修改配置。如果要控制日誌記錄配置,則可以提供--skip-log-setup標誌,該標誌將忽略其他參數。

Options選項

--skip-log-setup
禁用Locust的日誌記錄設置。相反,配置是由Locust test或Python默認設置提供配置。

--loglevel
在DEBUG/INFO/WARNING/ERROR/CRITICAL之間選擇。默認值爲INFO。簡寫爲-L

--logfile
日誌文件的路徑。如果未設置,則日誌將轉到stdout / stderr。

Locust API

API的話以官網爲準,以下是官網鏈接

API 官網鏈接

Locust 類

class Locust

表示一個策劃並將要對系統進行負載測試的“用戶”。
此用戶的行爲由**task_set**屬性定義,該屬性應該指向TaskSet類。
此類通常應由定義某種客戶端的類繼承。例如,在對HTTP系統進行負載測試時,您可能希望使用HttpLocust類。
task_set= None
TaskSet類,定義此Locust的執行行爲

wait_time= None
該方法,返回執行Locust任務之間的時間(以秒爲單位)。可以爲單個TaskSet覆蓋。
例如:

from locust import Locust, between
class User(Locust):
    wait_time = between(3, 25)

weight= 10
Locust被選中執行的概率。權重越高,被選中的機會越大。

HTTPLocust 類

class HttpLocust

表示一個策劃並將要對系統進行負載測試的HTTP“用戶”。
該HTTP用戶的行爲由**task_set**屬性定義,該屬性應該指向TaskSet類。
這個類在實例化時會創建一個 client 屬性,這個屬性的值是一個支持在請求間保持用戶會話(user session)的 HTTP 客戶端。

client=None
在 locust 實例化時創建的 HttpSession 實例。客戶端支持 cookies,因此在 HTTP 請求間保持會話。

TaskSet類

class TaskSet(parent)

該類定義locust用戶將要執行的一組任務。

當 TaskSet開始運行時,它將從 tasks 屬性中選擇一個任務並執行,然後調用這個任務的 wait_function 方法,之後再調用另一個任務,以此類推。
其中 wait_function 方法定義並返回一個以毫秒爲單位的睡眠時間,wait_function 方法定義的睡眠時間的默認是介於 min_wait 和 max_wait 之間且均勻分佈的隨機數;然後它將調度另一個任務執行,等等。

TaskSets可以嵌套,這意味着一個 TaskSet 的 tasks 屬性可以包含其他的 TaskSet。如果計劃執行嵌套的 TaskSet ,則將實例化它並從當前執行的 TaskSet 進行調用。然後,當前運行的 TaskSet 中的執行將被移交給嵌套的 TaskSet ,嵌套的 TaskSet 將繼續運行,直到遇到由 TaskSet.interrupt() 方法拋出的 InterruptTaskSet 異常時終止。(然後在第一個任務集中繼續執行)。

client
引用根Locust實例的client屬性。

interrupt(reschedule=True)
中斷TaskSet並將執行控制移交給父TaskSet。

如果reschedule的值爲True,父 locust 將立即重新調度並執行下一個任務。

這個方法不應該由根 TaskSet(即立即附加到 Locust 類的 task_set 屬性)調用,而應該由層次結構中更深層次的嵌套 TaskSet 類調用。

locust= None
當TaskSet實例化後,會引用根Locust類實例。

parent= None
實例化TaskSet時,將引用父TaskSet或Locust類實例。對於嵌套TaskSet類很有用。

schedule_task(task_callable, args=None, kwargs=None, first=False)
將任務添加到Locust的任務執行隊列中。
參數:

  • task_callable: 要調度的Locust任務計劃表
  • args: 將傳遞給可調用任務(task_callable)的參數
  • kwargs: 關鍵字字典參數,將傳遞給可調用(task_callable)的任務.
  • first: 可選關鍵字參數。如果爲 True,任務會被放到隊列的首位。

tasks= []
列表中包含表示 locust 用戶任務的可調用對象。

如果該參數值是一個列表,那麼將從中隨機挑選任務進行執行。

如果該參數值是一個元素爲二元組 (callable, int) 的列表或元素爲 callable: int 的字典,那麼將隨機選擇要執行的任務,但是每個任務將根據其對應的 int 類型的值進行加權。所以在下面的例子中,ThreadPage 被選中的可能性是 write_post 的15倍:

class ForumPage(TaskSet):
    tasks = {ThreadPage:15, write_post:1}

wait_time()
該方法返回執行任務之間的時間(以秒爲單位)。
例如:

from locust import TaskSet, between
class Tasks(TaskSet):
    wait_time = between(3, 25)

任務裝飾器 task decorator

task(weight=1)
使用一個便捷裝的飾器,以便能夠爲類中的TaskSet內聯聲明任務。

class ForumPage(TaskSet):
    @task(100)
    def read_thread(self):
        pass
    
    @task(7)
    def create_thread(self):
        pass

TaskSequence類(任務序列類)

classTaskSequence(parent)
定義 locust 用戶將要執行的任務序列。

當 TaskSequence 開始執行時,它將從 tasks 屬性值中根據任務的索引選擇一個任務進行執行,然後調用它的定義了一個睡眠時間的 wait_fucntion 方法。wait_function 定義的睡眠時間默認爲介於 min_wait 和 max_wait 之間且均勻分佈的一個隨機數,單位爲毫秒。然後再調用索引爲 index + 1 / % 的任務,以此類推。

TaskSequence 可以與 TaskSet 嵌套,這意味着 TaskSequence 的 tasks 屬性可以包含 TaskSet 實例和其他TaskSequence 實例。如果計劃執行嵌套的 TaskSet,則將實例化它並從當前執行的 TaskSet 調用它。然後,當前運行的 TaskSet 中的執行將被移交給嵌套的 TaskSet ,這個嵌套的 TaskSet 將繼續運行,直到遇到由 TaskSet.interrupt()拋出 InterruptTaskSet異常時終止,然後在第一個 TaskSet 中繼續執行。

在這個類中,任務應該被定義成一個列表,或者簡單地由 @task_seq 裝飾器定義。

client
引用根 Locust 實例的client屬性。

interrupt(reschedule=True)
中斷 TaskSet 並將執行控制權交給父 TaskSet。

如果 reschedule 的值爲 True,父 locust 將立即重新調度並執行下一個任務。

這個方法不應該由根 TaskSet (即立即附加到 Locust 類的 task_set 屬性)調用,而應該由層次結構中更深層次的嵌套 TaskSet 類調用。

schedule_task(task_callable, args=None, kwargs=None, first=False)
添加一個任務到Locust 的任務執行隊列。
參數:

  • task_callable:要調度的 locust 任務。
  • args:要傳遞給 task_callable 的參數。
  • kwargs:要傳遞給 task_callable 的關鍵字參數的字典。
  • first:可選關鍵字參數。如果爲 True,任務會被放到隊列的首位。

wait_time()
該方法返回執行任務之間的時間(以秒爲單位)。
例如:

from locust import TaskSet, between
class Tasks(TaskSet):
    wait_time = between(3, 25)

seq_task裝飾器

seq_task(order)
用於在類中內聯聲明 TaskSequence 的任務。
例如:

class NormalUser(TaskSequence):
    @seq_task(1)
    def login_first(self):
        pass

    @seq_task(2)
    @task(25) # You can also set the weight in order to execute the task for `weight` times one after another.
    def then_read_thread(self):
        pass

    @seq_task(3)
    def then_logout(self):
        pass

HttpSession 類

between(min_wait, max_wait)
返回一個函數,該函數將在min_wait和max_wait之間返回一個隨機數。
例如:

class User(Locust):
    # wait between 3.0 and 10.5 seconds after each task
    wait_time = between(3.0, 10.5)

constant(wait_time)
返回一個函數,該函數只返回wait_time參數指定的數字。
例如:

class User(Locust):
    wait_time = constant(3)

constant_pacing(wait_time)
返回一個函數,該函數將跟蹤任務的運行時間,每次調用它時,它將返回一個等待時間,該等待時間將嘗試使任務執行之間的總時間等於wait_time參數指定的時間。

在以下示例中,無論任務執行時間如何,任務總是每秒執行一次:

class User(Locust):
    wait_time = constant_pacing(1)
    class task_set(TaskSet):
        @task
        def my_task(self):
            time.sleep(random.random())

如果任務執行超過了指定的wait_time,則在開始下一個任務之前的等待時間爲0。

HttpSession 類

**class HttpSession(base_url, *args, kwargs)
用於執行Web請求和在請求之間保留(會話)Cookie的類(以便能夠登錄和註銷網站)。每個請求都被記錄下來,以便Locust可以顯示統計信息。

這是Python的 requests 庫的requests.Session類的拓展,工作原理與是極其相似的。然而,發送請求的方法(get、post、delete、put、head、options、patch、request)現在可以接受一個 url 參數,這個參數只是 URL的路徑部分,在這種情況下,URL的主機部分將取 HttpSession.base_url (繼承自一個 Locust 類的 host 屬性)的值。

發送請求的每個方法還接受兩個額外的可選參數,這些參數是特定於 Locust ,在Python的 requests 庫中不存在的:
參數:

  • name
    可選參數。可以指定爲 Locust 的統計信息中的標籤,用於代替 URL 路徑。這可以用於將被請求的不同 URL 分組到 Locust 統計數據中的一個條目中。

  • catch_response
    可選參數。如果要設置,可以是一個布爾值。可以用來使請求返回爲作爲with 語句的參數的上下文管理器。這將允許根據響應內容將請求標記爲失敗,即使響應代碼是 ok (2xx) ,反之亦然。可以使用 catch_response 捕捉請求,然後將其標記爲成功,即使響應代碼不是 ok (例如 500 或 404)。

__init__(base_url, \*args, \*\* kwargs)
x.init(…) 初始化x; see help(type(x)) for signature

delete(url, \*\*kwargs)
發送一個 DELETE 請求,返回一個 Response 對象。
參數:
url:新 Request 對象的URL。
**kwargs:request 的可選參數。
返回值類型:requests.Response 對象。

get(url, \*\*kwargs)
發送一個 GET 請求,返回一個 Response 對象。
參數:
url:新 Request 對象的URL。
**kwargs:request 的可選參數。
返回值類型:requests.Response 對象。

head(url, \*\*kwargs)
發送一個 HEAD 請求,返回一個 Response 對象。
參數:
url:新 Request 對象的URL。
**kwargs:request 的可選參數。
返回值類型:requests.Response 對象。

options(url, \*\*kwargs)
發送一個 OPTIONS 請求,返回一個 Response 對象。
參數:
url:新 Request 對象的URL。
**kwargs:request 的可選參數。
返回值類型:requests.Response 對象。

patch(url,data=None , \*\*kwargs)
發送一個 PATCH 請求,返回一個 Response 對象。
參數:
url:新 Request 對象的URL。
data:可選參數。發送到請求主體中的字典、bytes 或 file-like 對象。
**kwargs:request 的可選參數。
返回值類型:requests.Response 對象。

post(url,data=None , json=None, \*\*kwargs)
發送一個 POST 請求,返回一個 Response 對象。
參數:
url:新 Request 對象的URL。
data:可選參數。發送到請求主體中的字典、bytes 或 file-like 對象。
**kwargs:request 的可選參數。
json:可選參數。要發送到請求主體中的 json 格式數據。
返回值類型:requests.Response 對象。

put(url,data=None , \*\*kwargs)
發送一個 PUT 請求,返回一個 Response 對象。
參數
url:新 Request 對象的URL。
data:可選參數。發送到請求主體中的字典、bytes 或 file-like 對象。
**kwargs:request 的可選參數。
返回值類型:requests.Response 對象。

request(method, url, name=None , catch_response=False, **kwargs)
構造併發送一個requests.Request 。返回 requests.Response對象。

參數:
method:新 Request 對象的方法。
url:新 Request 對象的URL。
name:可選參數。
可以指定爲 Locust 的統計信息中的標籤,用於代替 URL 路徑。這可以用於將被請求的不同 URL 分組到 Locust 統計數據中的一個條目中。
catch_response可選參數。如果要設置,可以是一個布爾值。可以用來使請求返回爲作爲with 語句的參數的上下文管理器。這將允許根據響應內容將請求標記爲失敗,即使響應代碼是 ok (2xx) ,反之亦然。可以使用 catch_response捕捉請求,然後將其標記爲成功,即使響應代碼不是 ok (例如 500 或 404)。
params:可選參數。要發送到Request的查詢字符串的字典或 bytes 對象。
data:可選參數。要發送到 Request主體中的字典或 bytes 對象。
headers:可選參數。與 Request一起發送的表示 HTTP headers 的字典。
cookies:可選參數。與 Request一起發送的表示 cookies 的 dict 或 CookieJar 對象。
files:可選參數。用於多部分編碼上傳的元素爲 filename: filename: file-like-objects 的字典。
auth:可選參數:用於啓用 Basic/Digest或自定義的 HTTP Auth 的元組或可調用對象。
timeout:可選參數。以浮點數或(連接超時、讀取超時)元組的形式等待服務器發送數據的時間(以秒爲單位)。
allow_redirects:可選參數。布爾類型。默認值爲 True。 表示是否允許重定向。
proxies:可選參數。字典類型。鍵表示代理使用的協議,鍵值表示代理的URL。
stream:可選參數。是否立即下載響應內容。默認值爲 False
verify:可選參數。如果爲True,則會驗證 SSL 證書。也可以提供一個 CA_BUNDLE 路徑。
cert:可選參數。如果提供一個字符串。那麼應該是指向SSL 客戶端證書(.pem文件)的路徑;如果是一個元組,則應該是 (‘cert’, ‘key’)。

Response類

這個類其實是位於python-requests庫中的,但是由於 Locust在構造HTTP 請求的時候要用到這個類,並且在編寫 Locust負載測試時,這個類也非常重要,所以就把這個類包含在了 API 文檔裏。您還可以查看請求文檔中的Response類。

class Response
Response對象,它包含服務器對HTTP請求的響應。

apparent_encoding
明顯的編碼,由chardet庫提供。

close()
用於釋放鏈接。一旦調用此方法,就不能再次訪問基礎raw對象。
注意:通常不應該顯式調用它。

content
響應的內容,以字節爲單位。

cookies= None
服務器發回的一堆cookie。

elapsed= None
發送請求到響應到達之間的時間間隔(使用 timedelta 對象表示)。此屬性專門度量從發送請求的第一個字節到完成對報頭的解析所花費的時間。因此,它不受響應內容或 stream 關鍵字參數值的影響。

encoding= None
訪問 r.text 時解碼操作要用到的編碼方式。

headers= None
不區分大小寫的響應頭字典。
例如,headers['content-encoding'] 將會返回響應頭中鍵爲 Content-Encoding 的鍵值。

history= None
請求歷史記錄中的響應對象列表。任何重定向響應都將在這裏結束。該列表從最早的請求到最近的請求進行排序。

is_permanent_redirect
如果此響應是重定向的永久版本之一,則返回 True,否則返回 False。

is_redirect
如果此響應是可以自動處理的格式良好的HTTP重定向(通過 session.resolve_reredirect() 判斷),則返回True,否則返回 False。

iter_content(chunk_size=1, decode_unicode=False)
迭代響應數據。當對請求設置stream=True時,這可以避免立即將內容讀入內存以獲得較大的響應。數據塊大小是應該讀入內存的字節數。這不一定是解碼時返回的每個項的長度。
chunk_size的類型必須是int或None。None的值將根據流的值發揮不同的功能。
stream=True將在到達數據塊時讀取數據,無論塊的大小如何。
如果stream=False,則以單個塊的形式返回數據。

如果decode_unicode爲True,那麼將使用基於響應的最佳可用編碼對內容進行解碼。

iter_lines(chunk_size=512, decode_unicode=False, delimiter=None)
迭代響應數據,一次一行。當對請求設置stream=True時,這可以避免立即將內容讀入內存以獲得較大的響應。
注意:這種方法是不安全的。

json(**kwargs)
返回響應的 json 編碼內容(如果有的話)。
**kwargs-- 表示要傳給jason.loads函數的可選參數。
ValueError --如果響應的主體中不包含有效的 json 數據,則將引發 ValueError 異常。

links
返回已解析的響應頭鏈接(如果有的話)。

next
返回一個PreparedRequest 對象,用於表示重定向鏈中的下一個請求(如果有的話)。

ok
如果 status_code 小於400,返回 True;如果不小於400,返回 False。

此屬性檢查響應的狀態代碼是否在400到600之間,以查看是否存在客戶端錯誤或服務器錯誤。如果狀態碼在200到400之間,則返回 True ,而不是檢查響應代碼是否爲 200 OK

raise_for_status()
如果發生HTTPError,則引發存儲的HTTPError

reason= None
響應HTTP狀態的文本原因.
例如: “Not Found” 或者 “OK”.

request= None
這是響應的PreparedRequest對象。

status_code= None
響應的HTTP狀態的整數代碼。
例如404或200。

text
使用Unicode字符表示的響應的內容。
如果 Response.encoding 是 None,則使用 chardet猜測編碼。
響應內容的編碼按照 RFC 2616 的規定,由 HTTP headers 唯一確定。如果可以利用非 HTTP 知識更好地猜測編碼,應該在訪問該特性之前爲r.encoding設置合適的值。

url= None
響應的最終URL位置。

ResponseContextManager類

class ResponseContextManager(response)

可以充當上下文管理器的 Response 類,提供手動控制HTTP 請求在在 Locost 的統計數據中應該標記爲成功還是失敗的能力。

這個類是 Response 類的子類。包含兩個額外的方法:successfailure

failure(exc)
將響應報告爲失敗。
其中參數 exc 可以是一個Python的異常類或者一個字符串。如果是一個字符串,那麼將使用這個字符串來實例化 CatchResponseError 類。
例如:

with self.client.get("/", catch_response=True) as response:
    if response.content == b"":
        response.failure("No data")

success()
報告響應成功
例如:

with self.client.get("/does/not/exist", catch_response=True) as response:
    if response.status_code == 404:
        response.success()

InterruptTaskSet異常
exception InterruptTaskSet(reschedule=True)
在 Locust 任務內拋出這個異常時,將會中斷這個 Locust 正在執行的當前任務。

事件鉤子

事件鉤子都是 locust.events.EventHook 類的實例。

class EventHook
簡單事件類,用於爲 locust 中不同類型的事件提供鉤子。

下面的代碼演示如何使用這個類:

my_event = EventHook()
def on_my_event(a, b, **kw):
    print "Event was fired with arguments: %s, %s" % (a, b)
my_event += on_my_event
my_event.fire(a="foo", b="bar")

如果 reverse 的值爲 True,則處理程序將按照插入時的相反順序運行。

注意: 強烈建議你在事件監聽器中添加通配符關鍵字參數,以防止在以後的版本中添加新參數時代碼中斷。

可用的鉤子

下面的事件鉤子在 locust.events 模塊下可用:
request_success= <locust.events.EventHook object>
當一個請求成功完成時觸發。
監聽者應該使用如下參數:

  • request_type:使用的請求方法。
  • name:被調用的URL的路徑(如果在對客戶端的調用中使用了名稱,則重寫名稱)。
  • response_time:使用毫秒錶示的響應時間。
  • response_length:響應的 Content-Length 值。

request_failure= <locust.events.EventHook object>
當一個請求失敗時觸發。
事件觸發式將使用如下參數:

  • request_type:使用的請求方法。
  • name:被調用的URL的路徑(如果在對客戶端的調用中使用了名稱,則重寫名稱)。
  • response_time:用毫秒錶示的從發出請求到拋出異常時的時間間隔。
  • exception:拋出的異常的實例。

locust_error= <locust.events.EventHook object>
當 Locust 類的執行過程中出現異常時觸發。
事件觸發式將使用如下參數:

  • locust_instance:異常發生時的 Locust 類的實例。
  • exception:拋出的異常。
  • tb:回溯對象(從 sys.exc_info()[2] 得到)

report_to_master= <locust.events.EventHook object>
當 Locust 在 -slave 模式下運行時使用。用於將數據附加到定期發送給主服務器的數據字典上。當報告要發送到主服務器時,它會定期觸發。

注意: Locust 使用的鍵 ‘stats’ 和 ‘errors’ 不應該被覆蓋。

事件觸發式將使用如下參數:

  • client_id:正在運行的 Locust 進程的客戶端 ID。
  • data:可修改的數據字典,以便附加應發送到主服務器的數據。

slave_report= <locust.events.EventHook object>
當 locust 在 -master 模式下運行使用。並在 Locust 主服務器從從屬服務器收到報告時觸發。
此事件可用於聚合來自 Locust 從屬服務器的數據。
事件觸發式將使用如下參數:

  • client_id:報告 Locust 從屬服務器的客戶端 ID。
  • data:來自從屬節點的數據字典。

hatch_complete= <locust.events.EventHook object>
當所有 locust 用戶都已經生成時觸發。
事件觸發式將使用如下參數:

  • user_count:孵化出的用戶數量。

quitting= <locust.events.EventHook object>
在退出 locust 進程時觸發。

第三方工具

支持其他採樣器協議,報告等。
Locust 插件

無需手動步驟即可自動執行分佈式運行
Locust集羣(蝗蟲羣)

使用其他語言
Locust主服務器和Locust從服務器通過交換msgpack消息進行通信,這是許多語言所支持的。因此,您可以使用任何喜歡的語言編寫Locust任務。爲了方便起見,一些庫充當了從屬運行程序。他們運行你的Locust任務,並定期向master報告。

Golang
Boomer

Java
Locust4j
Swarm

配置管理
部署Locust很容易,但是有些工具仍然可以提供一定程度的便利。

tinx.locust是Ansible的一個安裝角色,用於配置和控制Locust系統服務,或使用ansible-container構建Locust docker映像。還管理locustfile和相應的測試數據。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章