1、寫在前面html
官網: https://www.locust.io/node
官方使用文檔:https://docs.locust.io/en/latest/python
大併發量測試時,建議在linux系統下進行。linux
2、Locust安裝nginx
1.一、 ---> pip3 install locust
git
1.2 、 經過GitHub上克隆項目安裝(Python3推薦):https://github.com/locustio/locust ,而後執行 ...\locust> python setup.py install
github
二、安裝 pyzmqgolang
If you intend to run Locust distributed across multiple processes/machines, we recommend you to also install pyzmq.web
若是打算運行Locust 分佈在多個進程/機器,須要安裝pyzmq.算法
經過pip命令安裝。 /> pip install pyzmq
三、安裝成功,CMD敲入命令驗證。 /> locust --help
Options: -h, --help show this help message and exit -H HOST, --host=HOST Host to load test in the following format: http://10.21.32.33
--web-host=WEB_HOST Host to bind the web interface to. Defaults to '' (all interfaces) -P PORT, --port=PORT, --web-port=PORT Port on which to run web host -f LOCUSTFILE, --locustfile=LOCUSTFILE Python module file to import, e.g. '../other.py'. Default: locustfile --master Set locust to run in distributed mode with this process as master --slave Set locust to run in distributed mode with this process as slave --master-host=MASTER_HOST Host or IP address of locust master for distributed load testing. Only used when running with --slave. Defaults to 127.0.0.1. --master-port=MASTER_PORT The port to connect to that is used by the locust master for distributed load testing. Only used when running with --slave. Defaults to 5557. Note that slaves will also connect to the master node on this port + 1. --master-bind-host=MASTER_BIND_HOST Interfaces (hostname, ip) that locust master should bind to. Only used when running with --master. Defaults to * (all available interfaces). --master-bind-port=MASTER_BIND_PORT Port that locust master should bind to. Only used when running with --master. Defaults to 5557. Note that Locust will also use this port + 1, so by default the master node will bind to 5557 and 5558. --no-web Disable the web interface, and instead start running the test immediately. Requires -c and -r to be specified. -c NUM_CLIENTS, --clients=NUM_CLIENTS Number of concurrent clients. Only used together with --no-web -r HATCH_RATE, --hatch-rate=HATCH_RATE The rate per second in which clients are spawned. Only used together with --no-web -n NUM_REQUESTS, --num-request=NUM_REQUESTS Number of requests to perform. Only used together with --no-web -L LOGLEVEL, --loglevel=LOGLEVEL Choose between DEBUG/INFO/WARNING/ERROR/CRITICAL. Default is INFO. --logfile=LOGFILE Path to log file. If not set, log will go to stdout/stderr --print-stats Print stats in the console --only-summary Only print the summary stats -l, --list Show list of possible locust classes and exit --show-task-ratio print table of the locust classes' task execution
ratio --show-task-ratio-json print json data of the locust classes' task execution
ratio -V, --version show program's version number and exit
參數說明:
-h, --help 查看幫助 -H HOST, --host=HOST 指定被測試的主機,採用以格式:http://10.21.32.33
--web-host=WEB_HOST 指定運行 Locust Web 頁面的主機,默認爲空 ''。 -P PORT, --port=PORT, --web-port=PORT 指定 --web-host 的端口,默認是8089 -f LOCUSTFILE, --locustfile=LOCUSTFILE 指定運行 Locust 性能測試文件,默認爲: locustfile.py --csv=CSVFILEBASE, --csv-base-name=CSVFILEBASE 以CSV格式存儲當前請求測試數據。 --master Locust 分佈式模式使用,當前節點爲 master 節點。 --slave Locust 分佈式模式使用,當前節點爲 slave 節點。 --master-host=MASTER_HOST 分佈式模式運行,設置 master 節點的主機或 IP 地址,只在與 --slave 節點一塊兒運行時使用,默認爲:127.0.0.1. --master-port=MASTER_PORT 分佈式模式運行, 設置 master 節點的端口號,只在與 --slave 節點一塊兒運行時使用,默認爲:5557。注意,slave 節點也將鏈接到這個端口+1 上的 master 節點。 --master-bind-host=MASTER_BIND_HOST Interfaces (hostname, ip) that locust master should bind to. Only used when running with --master. Defaults to * (all available interfaces). --master-bind-port=MASTER_BIND_PORT Port that locust master should bind to. Only used when running with --master. Defaults to 5557. Note that Locust will also use this port + 1, so by default the master node will bind to 5557 and 5558. --expect-slaves=EXPECT_SLAVES How many slaves master should expect to connect before starting the test (only when --no-web used). --no-web no-web 模式運行測試,須要 -c 和 -r 配合使用. -c NUM_CLIENTS, --clients=NUM_CLIENTS 指定併發用戶數,做用於 --no-web 模式。 -r HATCH_RATE, --hatch-rate=HATCH_RATE 指定每秒啓動的用戶數,做用於 --no-web 模式。 -t RUN_TIME, --run-time=RUN_TIME 設置運行時間, 例如: (300s, 20m, 3h, 1h30m). 做用於 --no-web 模式。 -L LOGLEVEL, --loglevel=LOGLEVEL 選擇 log 級別(DEBUG/INFO/WARNING/ERROR/CRITICAL). 默認是 INFO. --logfile=LOGFILE 日誌文件路徑。若是沒有設置,日誌將去 stdout/stderr --print-stats 在控制檯中打印數據 --only-summary 只打印摘要統計 --no-reset-stats Do not reset statistics once hatching has been completed。 -l, --list 顯示測試類, 配置 -f 參數使用 --show-task-ratio 打印 locust 測試類的任務執行比例,配合 -f 參數使用. --show-task-ratio-json 以 json 格式打印 locust 測試類的任務執行比例,配合 -f 參數使用. -V, --version 查看當前 Locust 工具的版本.
四、Locust主要由下面的幾個庫構成:
1) gevent
gevent是一種基於協程的Python網絡庫,它用到Greenlet提供的,封裝了libevent事件循環的高層同步API。
2) flask
Python編寫的輕量級Web應用框架。
3) requests
Python Http庫
4) msgpack-python
MessagePack是一種快速、緊湊的二進制序列化格式,適用於相似JSON的數據格式。msgpack-python主要提供MessagePack數據序列化及反序列化的方法。
5) six
Python2和3兼容庫,用來封裝Python2和Python3之間的差別性
6) pyzmq
pyzmq是zeromq(一種通訊隊列)的Python綁定,主要用來實現Locust的分佈式模式運行
當咱們在安裝 Locust 時,它會檢測咱們當前的 Python 環境是否已經安裝了這些庫,若是沒有安裝,它會先把這些庫一一裝上。而且對這些庫版本有要求,有些是必須等於某版本,有些是大於某版本。咱們也能夠事先把這些庫所有按要求裝好,再安裝Locust時就會快上許多。
3、編寫接口壓測腳本文件locustfile.py
1 from locust import HttpLocust, TaskSet, task 2
3 class ScriptTasks(TaskSet): 4 def on_start(self): 5 self.client.post("/login", { 6 "username": "test", 7 "password": "123456"
8 }) 9
10 @task(2) 11 def index(self): 12 self.client.get("/") 13
14 @task(1) 15 def about(self): 16 self.client.get("/about/") 17
18 @task(1) 19 def demo(self): 20 payload={} 21 headers={} 22 self.client.post("/demo/",data=payload, headers=headers) 23
24 class WebsiteUser(HttpLocust): 25 task_set = ScriptTasks 26 host = "http://example.com"
27 min_wait = 1000
28 max_wait = 5000
腳本解讀:
1、建立ScriptTasks()類繼承TaskSet類: 用於定義測試業務。 二、建立index()、about()、demo()方法分別表示一個行爲,訪問http://example.com。用@task() 裝飾該方法爲一個任務。一、2表示一個Locust實例被挑選執行的權重,數值越大,執行頻率越高。在當前ScriptTasks()行爲下的三個方法得執行比例爲2:1:1 3、WebsiteUser()類: 用於定義模擬用戶。 4、task_set : 指向一個定義了的用戶行爲類。 5、host: 指定被測試應用的URL的地址 6、min_wait : 用戶執行任務之間等待時間的下界,單位:毫秒。 七、max_wait : 用戶執行任務之間等待時間的上界,單位:毫秒。
腳本使用場景解讀:
在這個示例中,定義了針對http://example.com
網站的測試場景:先模擬用戶登陸系統,而後隨機地訪問首頁(/
)和關於頁面(/about/
),請求比例爲2:1,
demo方法主要用來闡述client對post接口的處理方式;而且,在測試過程當中,兩次請求的間隔時間爲1->
5
秒間的隨機值。
從腳本中能夠看出,腳本主要包含兩個類,一個是WebsiteUser
(繼承自HttpLocust
,而HttpLocust
繼承自Locust
),另外一個是ScriptTasks
(繼承自TaskSet
)。事實上,在Locust
的測試腳本中,全部業務測試場景都是在Locust
和TaskSet
兩個類的繼承子類中進行描的。
那如何理解Locust
和TaskSet
這兩個類呢?簡單地說,Locust類
就比如是一羣蝗蟲,而每一隻蝗蟲就是一個類的實例。相應的,TaskSet類
就比如是蝗蟲的大腦,控制着蝗蟲的具體行爲,即實際業務場景測試對應的任務集。
4、Locust類
實例腳本
僞代碼:
from locust import HttpLocust, TaskSet, task class WebsiteTasks(TaskSet): def on_start(self): #進行初始化的工做,每一個Locust用戶開始作的第一件事 payload = { "username": "test_user", "password": "123456", } header = { "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36", } self.client.post("/login",data=payload,headers=header)#self.client屬性使用Python request庫的全部方法,調用和使用方法和requests徹底一致; @task(5) #經過@task()裝飾的方法爲一個事務,方法的參數用於指定該行爲的執行權重,參數越大每次被虛擬用戶執行的機率越高,默認爲1 def index(self): self.client.get("/") @task(1) def about(self): self.client.get("/about/") class WebsiteUser(HttpLocust): host = "https://github.com/" #被測系統的host,在終端中啓動locust時沒有指定--host參數時纔會用到 task_set = WebsiteTasks #TaskSet類,該類定義用戶任務信息,必填。這裏就是:WebsiteTasks類名,由於該類繼承TaskSet; min_wait = 5000 #每一個用戶執行兩個任務間隔時間的上下限(毫秒),具體數值在上下限中隨機取值,若不指定默認間隔時間固定爲1秒 max_wait = 15000
僞代碼中對https://github.com/網站的測試場景,先模擬用戶登陸系統,而後隨機訪問首頁/和/about/,請求比例5:1,而且在測試過程當中,兩次請求的間隔時間1-5秒的隨機值;
on_start方法,在正式執行測試前執行一次,主要用於完成一些初始化的工做,例如登陸操做;
WebsiteTasks類中如何去調用 WebsiteUser(HttpLocust)類中定義的字段和方法呢?
經過在WebsiteTasks類中self.locust.xxoo xxoo就是咱們在WebsiteUser類中定義的字段或方法;
僞代碼:
from locust import HttpLocust, TaskSet, task import hashlib import queue class WebsiteTasks(TaskSet): @task(5) def index(self): data = self.locust.user_data_queue #獲取WebsiteUser裏面定義的ser_data_queue隊列 md5_data=self.locust.md5_encryption() #獲取WebsiteUser裏面定義的md5_encryption()方法 self.client.get("/") class WebsiteUser(HttpLocust): host = "https://github.com/" task_set = WebsiteTasks min_wait = 5000 max_wait = 15000 user_data_queue = queue.Queue() def md5_encryption(self,star): '''md5加密方法''' obj = hashlib.md5() obj.update(bytes(star,encoding="utf-8")) result = obj.hexdigest() return result
僞代碼中測試場景如何表達?
代碼主要包含兩個類:
在Locust測試腳本中,全部業務測試場景都是在Locust和TaskSet兩個類的繼承子類中進行描述;
簡單說:Locust類就相似一羣蝗蟲,而每隻蝗蟲就是一個類的實例。TaskSet類就相似蝗蟲的大腦,控制蝗蟲的具體行爲,即實際業務場景測試對應的任務集;
源碼中:class Locust(object)和class HttpLocust(Locust)
1 class Locust(object): 2 """ 3 Represents a "user" which is to be hatched and attack the system that is to be load tested. 4 5 The behaviour of this user is defined by the task_set attribute, which should point to a 6 :py:class:`TaskSet <locust.core.TaskSet>` class. 7 8 This class should usually be subclassed by a class that defines some kind of client. For 9 example when load testing an HTTP system, you probably want to use the 10 :py:class:`HttpLocust <locust.core.HttpLocust>` class. 11 """ 12 13 host = None 14 """Base hostname to swarm. i.e: http://127.0.0.1:1234""" 15 16 min_wait = 1000 17 """Minimum waiting time between the execution of locust tasks""" 18 19 max_wait = 1000 20 """Maximum waiting time between the execution of locust tasks""" 21 22 task_set = None 23 """TaskSet class that defines the execution behaviour of this locust""" 24 25 stop_timeout = None 26 """Number of seconds after which the Locust will die. If None it won't timeout.""" 27 28 weight = 10 29 """Probability of locust being chosen. The higher the weight, the greater is the chance of it being chosen.""" 30 31 client = NoClientWarningRaiser() 32 _catch_exceptions = True 33 34 def __init__(self): 35 super(Locust, self).__init__() 36 37 def run(self): 38 try: 39 self.task_set(self).run() 40 except StopLocust: 41 pass 42 except (RescheduleTask, RescheduleTaskImmediately) as e: 43 44 class HttpLocust(Locust): 45 """ 46 Represents an HTTP "user" which is to be hatched and attack the system that is to be load tested. 47 48 The behaviour of this user is defined by the task_set attribute, which should point to a 49 :py:class:`TaskSet <locust.core.TaskSet>` class. 50 51 This class creates a *client* attribute on instantiation which is an HTTP client with support 52 for keeping a user session between requests. 53 """ 54 55 client = None 56 """ 57 Instance of HttpSession that is created upon instantiation of Locust. 58 The client support cookies, and therefore keeps the session between HTTP requests. 59 """ 60 def __init__(self): 61 super(HttpLocust, self).__init__() 62 if self.host is None: 63 raise LocustError("You must specify the base host. Either in the host attribute in the Locust class, or on the command line using the --host option.") 64 self.client = HttpSession(base_url=self.host)
在Locust類中,靜態字段client即客戶端的請求方法,這裏的client字段沒有綁定客戶端請求方法,所以在使用Locust時,須要先繼承Locust類class HttpLocust(Locust),而後在self.client =HttpSession(base_url=self.host)綁定客戶端請求方法;
對於常見的HTTP(s)協議,Locust已經實現了HttpLocust類,其self.client=HttpSession(base_url=self.host),而HttpSession繼承自requests.Session。所以在測試HTTP(s)的Locust腳本中,能夠經過client屬性來使用Python requests庫的所 有方法,調用方式與 reqeusts徹底一致。另外,因爲requests.Session的使用,client的方法調用之間就自動具備了狀態記憶功能。常見的場景就是,在登陸系統後能夠維持登陸狀態的Session,從然後續HTTP請求操做都能帶上登陸狀態;
Locust類中,除了client屬性,還有幾個屬性須要關注:
Locust流程,測試開始後,每一個虛擬用戶(Locust實例)運行邏輯都會遵照以下規律:
class TaskSet
TaskSet類實現了虛擬用戶所執行任務的調度算法,包括規劃任務執行順序(schedule_task)、挑選下一個任務(execute_next_task)、執行任務(execute_task)、休眠等待(wait)、中斷控制(interrupt)等待。在此基礎上,就能夠在TaskSet子類中採用很是簡潔的方式來描述虛擬用戶的業務測試場景,對虛擬用戶的全部行爲進行組織和描述,並能夠對不一樣任務的權重進行配置。
@task
經過@task()裝飾的方法爲一個事務。方法的參數用於指定該行爲的執行權重。參數越大每次被虛擬用戶執行的機率越高。若是不設置默認爲1。
TaskSet子類中定義任務信息時,採起兩種方式:@task裝飾器和tasks屬性。
採用@task裝飾器定義任務信息時:
from locust import TaskSet, task class UserBehavior(TaskSet): @task(1) def test_job1(self): self.client.get('/test1') @task(3) def test_job2(self): self.client.get('/test2')
採用tasks屬性定義任務信息時
from locust import TaskSet def test_job1(obj): obj.client.get('/test1') def test_job2(obj): obj.client.get('/test2') class UserBehavior(TaskSet): tasks = {test_job1:1, test_job2:3} # tasks = [(test_job1,1), (test_job1,3)] # 兩種方式等價
上面兩種定義任務信息方式中,均設置了權重屬性,即執行test_job2的頻率是test_job1的兩倍。
若不指定,默認比例爲1:1。
高級用法:
關聯
在某些請求中,須要攜帶以前response中提取的參數,常見場景就是session_id。Python中可用經過re正則匹配,對於返回的html頁面,可用採用lxml庫來定位獲取須要的參數;
from locust import HttpLocust, TaskSet, task from lxml import etree class WebsiteTasks(TaskSet): def get_session(self,html): #關聯例子 tages = etree.HTML(html) return tages.xpath("//div[@class='btnbox']/input[@name='session']/@value")[0] def on_start(self): html = self.client.get('/index') session = self.get_session(html.text) payload = { "username": "test_user", "password": "123456", 'session' : session } header = { "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36", } self.client.post("/login",data=payload,headers=header) @task(5) def index(self): self.client.get("/") assert response['ErrorCode']==0 #斷言 @task(1) def about(self): self.client.get("/about/") class WebsiteUser(HttpLocust): host = "https://github.com/" task_set = WebsiteTasks min_wait = 5000 max_wait = 15000
參數化
做用:循環取數據,數據可重複使用
例如:模擬3個用戶併發請求網頁,共有100個URL地址,每一個虛擬用戶都會依次循環加載100個URL地址
from locust import TaskSet, task, HttpLocust class UserBehavior(TaskSet): def on_start(self): self.index = 0 @task def test_visit(self): url = self.locust.share_data[self.index] print('visit url: %s' % url) self.index = (self.index + 1) % len(self.locust.share_data) self.client.get(url) class WebsiteUser(HttpLocust): host = 'http://debugtalk.com' task_set = UserBehavior share_data = ['url1', 'url2', 'url3', 'url4', 'url5'] min_wait = 1000 max_wait = 3000
保證併發測試數據惟一性,不循環取數據;
全部併發虛擬用戶共享同一份測試數據,而且保證虛擬用戶使用的數據不重複;
例如:模擬3用戶併發註冊帳號,共有9個帳號,要求註冊帳號不重複,註冊完畢後結束測試:
採用隊列
from locust import TaskSet, task, HttpLocust import queue class UserBehavior(TaskSet): @task def test_register(self): try: data = self.locust.user_data_queue.get() except queue.Empty: print('account data run out, test ended.') exit(0) print('register with user: {}, pwd: {}'\ .format(data['username'], data['password'])) payload = { 'username': data['username'], 'password': data['password'] } self.client.post('/register', data=payload) class WebsiteUser(HttpLocust): host = 'http://debugtalk.com' task_set = UserBehavior user_data_queue = queue.Queue() for index in range(100): data = { "username": "test%04d" % index, "password": "pwd%04d" % index, "email": "test%04d@debugtalk.test" % index, "phone": "186%08d" % index, } user_data_queue.put_nowait(data) min_wait = 1000 max_wait = 3000
保證併發測試數據惟一性,循環取數據;
全部併發虛擬用戶共享同一份測試數據,保證併發虛擬用戶使用的數據不重複,而且數據可循環重複使用;
例如:模擬3個用戶併發登陸帳號,總共有9個帳號,要求併發登陸帳號不相同,但數據可循環使用;
from locust import TaskSet, task, HttpLocust import queue class UserBehavior(TaskSet): @task def test_register(self): try: data = self.locust.user_data_queue.get() except queue.Empty: print('account data run out, test ended') exit(0) print('register with user: {0}, pwd: {1}' .format(data['username'], data['password'])) payload = { 'username': data['username'], 'password': data['password'] } self.client.post('/register', data=payload) self.locust.user_data_queue.put_nowait(data) class WebsiteUser(HttpLocust): host = 'http://debugtalk.com' task_set = UserBehavior user_data_queue = queue.Queue() for index in range(100): data = { "username": "test%04d" % index, "password": "pwd%04d" % index, "email": "test%04d@debugtalk.test" % index, "phone": "186%08d" % index, } user_data_queue.put_nowait(data) min_wait = 1000 max_wait = 3000
斷言(即檢查點)
性能測試也須要設置斷言麼? 某些狀況下是須要,好比你在請求一個頁面時,就能夠經過狀態來判斷返回的 HTTP 狀態碼是否是 200。
經過with self.client.get("url地址",catch_response=True) as response的形式;
response.status_code獲取http響應碼進行判斷,失敗後會加到統計錯誤表中;
python自帶的斷言assert失敗後代碼就不會向下走,且失敗後不會被Locust報表統計進去;
默認不寫參數catch_response=False斷言無效,將catch_response=True才生效;
下面例子中:
首先使用python斷言對接口返回值進行判斷(python斷言不經過,代碼就不向下執行,get請求數爲0),經過後對該接口的http響應是否爲200進行判斷;
@task def all_interface(self): #豆瓣圖書api爲例子 with self.client.get("https://api.douban.com/v2/book/1220562",name="/LhcActivity/GetActConfig",catch_response=True) as response: assert response.json()['rating']['max']==10 #python斷言對接口返回值中的max字段進行斷言 if response.status_code ==200: #對http響應碼是否200進行判斷 response.success() else: response.failure("GetActConfig[Failed!]")
運行Locust
時,一般會使用到兩種運行模式:單進程運行和多進程分佈式運行。
Locust
全部的虛擬併發用戶均運行在單個Python
進程中,具體從使用形式上,又分爲no_web
和web
兩種形式。該種模式因爲單進程的緣由,並不能徹底發揮壓力機全部處理器的能力,所以主要用於調試腳本和小併發壓測的狀況。
當併發壓力要求較高時,就須要用到Locust
的多進程分佈式運行模式。從字面意思上看,你們可能第一反應就是多臺壓力機同時運行,每臺壓力機分擔負載一部分的壓力生成。的確,Locust
支持任意多臺壓力機(一主多從)的分佈式運行模式,但這裏說到的多進程分佈式運行模式還有另一種狀況,就是在同一臺壓力機上開啓多個slave
的狀況。這是由於當前階段大多數計算機的CPU都是多處理器(multiple processor cores
),單進程運行模式下只能用到一個處理器的能力,而經過在一臺壓力機上運行多個slave
,就能調用多個處理器的能力了。比較好的作法是,若是一臺壓力機有N
個處理器內核,那麼就在這臺壓力機上啓動一個master
,N
個slave
。固然,咱們也能夠啓動N
的倍數個slave
,可是根據個人試驗數據,效果跟N
個差很少,所以只須要啓動N
個slave
便可。
若是採用no_web
形式,則需使用--no-web
參數,並會用到以下幾個參數。
-c, --clients
:指定併發用戶數;-n, --num-request
:指定總執行測試次數;-r, --hatch-rate
:指定併發加壓速率,默認值位1。示例:
$ locust -f locustfile.py --host = xxxxx.com --no-web -c 1 -n 2
在此基礎上,當咱們想要調試Locust
腳本時,就能夠在腳本中須要調試的地方經過print
打印日誌,而後將併發數和總執行次數都指定爲1
$ locust -f locustfile.py --host = xxxxx.com --no-web -c 1 -n 1
執行測試
經過這種方式,咱們就能很方便地對Locust
腳本進行調試了。
Locust
腳本調試經過後,就算是完成了全部準備工做,能夠開始進行壓力測試了。
web形式啓動locust:
若是採用web
形式,,則一般狀況下無需指定其它額外參數,Locust
默認採用8089
端口啓動web
;若是要使用其它端口,就可使用以下參數進行指定。
-P, --port
:指定web端口,默認爲8089
.Locust
運行在本機,在瀏覽器中訪問http://localhost:8089
便可進入Locust
的Web管理頁面;若是Locust
運行在其它機器上,那麼在瀏覽器中訪問http://locust_machine_ip:8089
便可。多進程分佈式運行
無論是單機多進程
,仍是多機負載
模式,運行方式都是同樣的,都是先運行一個master
,再啓動多個slave
。
啓動master
時,須要使用--master
參數;一樣的,若是要使用8089
之外的端口,還須要使用-P, --port
參數。
D:\workSpaces\ApiAutoTest\TestCases\OpsUltraAPITest\MonitorAPITest>locust -f monitorAgent.py --master --port=8089 [2018-06-05 15:36:30,654] dengshihuang/INFO/locust.main: Starting web monitor at *:8089 [2018-06-05 15:36:30,684] dengshihuang/INFO/locust.main: Starting Locust 0.8.1
啓動
啓動後,還須要啓動slave
時須要使用--slave
參數;在slave
中,就不須要再指定端口了。masterslave
才能執行測試任務。
D:\workSpaces\ApiAutoTest\TestCases\OpsUltraAPITest\MonitorAPITest>locust -f monitorAgent.py --slave [2018-06-05 15:36:30,654] dengshihuang/INFO/locust.main: Starting web monitor at *:8089 [2018-06-05 15:36:30,684] dengshihuang/INFO/locust.main: Starting Locust 0.8.1
D:\workSpaces\ApiAutoTest\TestCases\OpsUltraAPITest\MonitorAPITest>locust -f monitorAgent.py --slave --master-host=<locust_machine_ip>
master
和slave
都啓動完畢後,就能夠在瀏覽器中經過http://locust_machine_ip:8089
進入Locust
的Web管理頁面了。使用方式跟單進程web
形式徹底相同,只是此時是經過多進程負載來生成併發壓力,在web
管理界面中也能看到實際的slave
數量。若是slave
與master
不在同一臺機器上,還須要經過--master-host
參數再指定master
的IP地址。
運行結果:
Number of users to simulate 設置虛擬用戶數,對應中no_web
模式的-c, --clients
參數;
Hatch rate(users spawned/second)每秒產生(啓動)的虛擬用戶數 , 對應着no_web
模式的-r, --hatch-rate
參數,默認爲1。點擊Start swarming 按鈕,開始運行性能測試。
上圖:啓動了一個 master 和兩個 slave,由兩個 slave 來向被測試系統發送請求
性能測試參數
Type: 請求的類型,例如GET/POST。
Name:請求的路徑。這裏爲百度首頁,即:https://www.baidu.com/
request:當前請求的數量。
fails:當前請求失敗的數量。
Median:中間值,單位毫秒,一半的服務器響應時間低於該值,而另外一半高於該值。
Average:平均值,單位毫秒,全部請求的平均響應時間。
Min:請求的最小服務器響應時間,單位毫秒。
Max:請求的最大服務器響應時間,單位毫秒。
Content Size:單個請求的大小,單位字節。
reqs/sec:是每秒鐘請求的個數。
相比於LoadRunner
,Locust
的結果展現十分簡單,主要就四個指標:併發數
、RPS
、響應時間
、異常率
。但對於大多數場景來講,這幾個指標已經足夠了。
在上圖中,RPS
和平均響應時間
這兩個指標顯示的值都是根據最近2秒請求響應數據計算獲得的統計值,咱們也能夠理解爲瞬時值。
若是想看性能指標數據的走勢,就能夠在Charts
欄查看。在這裏,能夠查看到RPS
和平均響應時間
在整個運行過程當中的波動狀況。
除了以上數據,Locust
還提供了整個運行過程數據的百分比統計值,例如咱們經常使用的90%響應時間
、響應時間中位值;平均響應時間和錯誤數的統計
,該數據能夠經過Download response time distribution CSV和Download request statistics CSV
得到,數據展現效果以下所示。
locust雖然使用方便,可是加壓性能和響應時間上面仍是有差距的,若是項目有很是大的併發加壓請求,能夠選擇wrk
對比方法與結果:
能夠準備兩臺服務器,服務器A做爲施壓方,服務器B做爲承壓方
服務器B上簡單的運行一個nginx服務就好了
服務器A上能夠安裝一些經常使用的壓測工具,好比locust、ab、wrk
我當時測下來,施壓能力上 wrk > golang >> ab > locust
由於locust一個進程只使用一核CPU,因此用locust壓測時,必須使用主從分佈式(zeromq通信)模式,並根據服務器CPU核數來起slave節點數
wrk約爲55K QPS
golang net/http 約 45K QPS
ab 大約 15K QPS
locust 最差,並且response time明顯比較長
-------------------------------------------------------------------
好文推薦:
一、https://debugtalk.com/post/locustplus-talk-about-performance-test/
這篇博客從性能測試方法、性能瓶頸定位、性能測試工具的基本組成、性能測試工具推薦(比較了loadrunner,jmeter,Locust優缺點)等方面作了深刻的介紹,推薦!
蝗蟲比Jmeter好的一點就是高併發,可是相對的很差的地方也有,就是須要另外的工具去監控服務器,並且須要去編寫代碼。