Locust是一款易於使用的分佈式用戶負載測試工具。它用於對網站(或其餘系統)進行負載測試,並肯定系統能夠處理多少併發用戶。
這個想法是,在測試期間,一羣蝗蟲(Locust)會攻擊你的網站。您定義了每一個蝗蟲Locust(或測試用戶)的行爲,而且實時地從Web UI監視羣集過程。這將有助於您在讓真正的用戶進入以前進行測試並識別代碼中的瓶頸。
Locust徹底基於事件,所以能夠在一臺計算機上支持數千個併發用戶。與許多其餘基於事件的應用程序相比,它不使用回調。相反,它經過協程(gevent)機制使用輕量級過程。每一個蝗蟲蜂擁到你的網站其實是在本身的進程內運行(或者是greenlet,這是正確的)。這容許您在Python中編寫很是富有表現力的場景,而不會使代碼複雜化。python
** gevent是第三方庫,經過greenlet實現協程。greenlet是python的並行處理的一個庫。 python 有一個很是有名的庫叫作 stackless ,用來作併發處理, 主要是弄了個叫作tasklet的微線程的東西, 而greenlet 跟stackless的最大區別是greenlet須要你本身來處理線程切換, 就是說,你須要本身指定如今執行哪一個greenlet再執行哪一個greenlet。**c++
Locust支持Python 2.7, 3.4, 3.5, and 3.6的版本,小編的環境是python3.6直接用pip安裝就行 pip install locustioweb
報錯ruby
下載安裝Microsoft visual c++14.0 ,安裝完成後,從新安裝locust併發
locust裏面請求是基於requests的,每一個方法請求和requests差很少,請求參數、方法、響應對象和requests同樣的使用,以前學過requests庫的,這裏就很是簡單了less
# 保存爲demo.py # coding:utf-8 from locust import HttpLocust,TaskSet,task class BlogDemo(TaskSet): '''用戶行爲:打開個人博客首頁demo''' @task(1) def open_blog(self): # 定義requests的請求頭 header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"} r = self.client.get("/yoyoketang", headers=header, verify=False) print(r.status_code) assert r.status_code == 200 class websitUser(HttpLocust): task_set = BlogDemo min_wait = 3000 # 單位毫秒 max_wait = 6000 # 單位毫秒 if __name__ == "__main__": import os os.system("locust -f demo.py --host=https://www.cnblogs.com")
代碼註解:
新建一個類BlogDemo(TaskSet),繼承TaskSet,該類下面寫一些準備請求的行爲(訪問的接口)
裏面的self.client調用get和post方法,跟requests是同樣的
@task裝飾該方法表示爲用戶行爲。括號裏面參數表示該行爲挑選執行的權重,數值越大,執行頻率越高,不設置默認是1dom
WebsiteUser()類用於設置性能測試。
task_set :指向一個定義了的用戶行爲類。
min_wait :用戶執行任務之間等待時間的下界,單位:毫秒。
max_wait :用戶執行任務之間等待時間的上界,單位:毫秒。編輯器
啓動locust能夠直接在pycharm裏面執行上面的代碼,運行後編輯器出現兩行
[2018-09-12 23:23:57,500] DESKTOP-HJ487C8/INFO/locust.main: Starting web monitor at *:8089
[2018-09-12 23:23:57,500] DESKTOP-HJ487C8/INFO/locust.main: Starting Locust 0.9.0分佈式
也能夠經過cmd執行函數
$ locust -f demo.py --host=https://www.cnblogs.com
三個圖標分別是
有不少網站不登陸的話,是沒法訪問到裏面的頁面的,這就須要先登陸了
實現場景:先登陸(只登陸一次),而後訪問頁面->個人地盤頁->產品頁->項目頁
下面是一個簡單的locustfile.py的簡單示例:
from locust import HttpLocust, TaskSet
def login(l): l.client.post("/login", {"username":"ellen_key", "password":"education"}) def logout(l): l.client.post("/logout", {"username":"ellen_key", "password":"education"}) def index(l): l.client.get("/") def profile(l): l.client.get("/profile") class UserBehavior(TaskSet): tasks = {index: 2, profile: 1} def on_start(self): login(self) def on_stop(self): logout(self) class WebsiteUser(HttpLocust): task_set = UserBehavior min_wait = 5000 max_wait = 9000
這裏咱們定義了許多Locust任務,它們是帶有一個參數(Locust類實例)的普通Python callables 。這些任務收集在tasks屬性的TaskSet類下 。而後咱們有一個表明用戶的 類,咱們在其中定義模擬用戶在執行任務之間應該等待多長時間,以及哪一個 類應該定義用戶的「行爲」。 類能夠繼承HttpLocust、TaskSet、TaskSet
HttpLocust類從繼承 Locust的類,並把它添加一個客戶端屬性,它是的一個實例 HttpSession,可用於使HTTP請求。
另外一種咱們能夠聲明任務的方法,一般是更方便,就是使用 @task裝飾器。如下代碼與上述代碼相同:
from locust import HttpLocust, TaskSet, task class UserBehavior(TaskSet): def on_start(self): """ on_start is called when a Locust start before any task is scheduled """ self.login() def on_stop(self): """ on_stop is called when the TaskSet is stopping """ self.logout() def login(self): self.client.post("/login", {"username":"ellen_key", "password":"education"}) def logout(self): self.client.post("/logout", {"username":"ellen_key", "password":"education"}) @task(2) def index(self): self.client.get("/") @task(1) def profile(self): self.client.get("/profile") class WebsiteUser(HttpLocust): task_set = UserBehavior min_wait = 5000 max_wait = 9000
在Locust類(以及HttpLocust 由於它是一個子類),也可讓一個在指定最小和最大等待時間毫秒,每一個模擬用戶之間的任務執行(min_wait和MAX_WAIT)以及其餘用戶的行爲。默認狀況下,時間是在min_wait和max_wait之間統一隨機選擇的,可是能夠經過將wait_function設置爲任意函數來使用任何用戶定義的時間分佈。例如,對於指數分佈的等待時間平均爲1秒:
import random class WebsiteUser(HttpLocust): task_set = UserBehaviour wait_function = lambda self: random.expovariate(1)*1000