Locust學(xué)習(xí)總結(jié)

簡介

Locust是一個使用Python編寫的可擴(kuò)展凛忿、分布式的開源性能測試工具澈灼。

優(yōu)點

  • 相比于Jmeter、LoadRunner這種基于GUI的工具而言店溢,Locust使用Python語言來描述測試場景使模擬用戶行為變得更加靈活和簡潔叁熔,除了Http(s)協(xié)議之外,Locust可以測試任意協(xié)議的系統(tǒng)床牧,只需要實現(xiàn)Python調(diào)用對應(yīng)協(xié)議的庫進(jìn)行請求即可(類似HttpLocust類)荣回。
  • Locust的并發(fā)機(jī)制采用協(xié)程的方式,相比于進(jìn)程和線程減少了系統(tǒng)級資源調(diào)度戈咳,因此單機(jī)的產(chǎn)生的并發(fā)能力相比于LoadRunner心软、jmeter得到了大幅的提升。

安裝

pip install locust

Locust腳本編寫

import queue
from locust import HttpLocust, TaskSet, task
from locust.clients import HttpSession
from sign import ParserData


class UserBehavior(TaskSet):

    parser_data = ParserData()  # 解析接口傳參類
    _client = 20
    version = 119
    user_info = None

    @staticmethod
    def get_user_info(response):
        r = response.json().get('content')
        return {
            'market_id': r.get('marketId'),
            'token': r.get('token')
        }

    def on_start(self):
        try:
            user, password = self.locust.users.get_nowait()
        except queue.Empty:
            print('test data run out. test ended.')
            exit(0)
        client = HttpSession(base_url='http://login.xxxx.cn')
        data = self.parser_data(loginName=user,
                                password=password,
                                client=self._client,
                                version=self.version)
        response = client.post(url='/login', data=data)
        self.user_info = self.get_user_info(response)
        self.locust.users.put_nowait((user, password))

    @task(2)
    def index(self):
        url = '/index'
        data = self.parser_data(market_id=self.user_info['market_id'],
                                client=self._client,
                                version=self.version,
                                pnum='3')
        headers = {'Authorization': 'Barer:' + self.user_info['token'],
                   'Accept': 'application/vnd.hs-api.v1+json'}
        with self.client.post(url=url, data=data, headers=headers,
                              verify=False, catch_response=True) as response:
            if response.status_code == 200:
                response.success()
            else:
                response.failure('http error.')

    @task(1)
    def shop_car_list(self):
        url = '/shopCar/list'
        data = self.parser_data(market_id=self.user_info['market_id'],
                                ischaidan='1',
                                client=self._client,
                                version=self.version)
        headers = {'Authorization': 'Bearer:' + self.user_info['token'],
                   'Accept': 'application/vnd.hs-api.v1+json'}
        with self.client.post(name='ShopCar', url=url, data=data, headers=headers,
                              verify=False, catch_response=True) as response:
            if response.status_code != 200 or "失敗" in response.text:
                response.failure('response error.')
            else:
                response.success()


class Stay(TaskSet):

    index = 0

    def on_start(self):
        self.index += 1

    @task
    def get_error(self):
        response = self.client.get('/1', name='error', allow_redirects=False,
                                   verify=False, catch_response=True)
        if response.status_code == 200:
            response.success()
        else:
            response.failure('http error.')

    @task
    def logout(self):
        self.interrupt()


class User(TaskSet):

    tasks = {Stay: 1}

    @task(1)
    def user(self):
        self.client.get('/', verify=False)


class WebsiteUser(HttpLocust):
    task_set = UserBehavior
    host = 'https://xxxx.api.xxxx.cn'
    min_wait = 1000
    max_wait = 3000
    users = queue.Queue()
    users.put_nowait(('user1', '1232'))
    users.put_nowait(('user2', '1234'))
    users.put_nowait(('user3', '1321'))
    weight = 3
    stop_timeout = 20


class WebsiteU(HttpLocust):
    task_set = User
    host = 'https://www.baidu.com'
    min_wait = 0
    max_wait = 0
    weight = 1
    stop_timeout = 60

簡單解釋下:

  • UserBehavior和WebsiteUser兩個類實現(xiàn)測試場景使用3個用戶賬號著蛙,每個用戶會去先登錄删铃,然后分別去查看首頁和進(jìn)入購物車頁面
  • 首先導(dǎo)入了需要用到的類,HttpLocust類為Locust子類踏堡,模擬客戶端的請求類猎唁,Taskset類為任務(wù)集類,task為任務(wù)裝飾器顷蟆。

Taskset

  • UserBehavior為Taskset子類诫隅,該類主要用來定義每個虛擬用戶的操作行為

  • Taskset子類中可以定義一個on_start方法在正式開始測試前只執(zhí)行一次,相當(dāng)與初始化操作(這里說的只執(zhí)行一次是每個虛擬用戶都會去執(zhí)行一次)帐偎,比如獲取登錄token等操作逐纬。

  • teskset類中的每個任務(wù)都需要用@task(weight=1)裝飾器去裝飾為一個任務(wù),weight為執(zhí)行的權(quán)重削樊,如果不裝飾豁生,locust不會認(rèn)為這是一個任務(wù),UserBehavior類中@task(1)、@task(2)裝飾器表示3個用戶里面有2個用戶去模擬執(zhí)行index方法沛硅,有1個用戶去執(zhí)行shop_car_list方法

  • taskset類中self.client屬性請求操作時傳入catch_response參數(shù)眼刃,設(shè)置為True,可以標(biāo)記響應(yīng)結(jié)果為成功或失敗摇肌,即使響應(yīng)是成功的擂红,也可以標(biāo)記為失敗,默認(rèn)為Fasle

  • taskset類中self.client屬性請求操作時有一個name參數(shù)围小,當(dāng)設(shè)置了name的值時昵骤,最后的請求結(jié)果展示中name字段會顯示這里定義的name值,相當(dāng)與給這個方法起了一個別名.

  • taskset類中interrupt(reschedule=True)方法在頂層的taskset類(即被指定到Locust子類中的taskset)中不可用肯适,reschedule為True時变秦,從被嵌套的任務(wù)中出來立即執(zhí)行新的任務(wù),如果為False從被嵌套的任務(wù)中出來會等待min_time-max_time之間的隨機(jī)時間框舔,然后再執(zhí)行新的任務(wù)蹦玫,這個方法主要用來跳出嵌套的任務(wù)集

HttpLocust

  • WebsiteUser為HttpLocust子類,該類是用來模擬用戶的類刘绣,定義了一些用戶信息樱溉,及請求方式

  • HttpLocust子類中task_set屬性用來指定模擬用戶執(zhí)行的操作,即Taskset子類

  • HttpLocust子類中的host屬性為被測試系統(tǒng)的host纬凤,當(dāng)命令行中沒有指定--host參數(shù)時福贞,此屬性會生效

  • HttpLocust子類中的min_wait、max_weight為最大等待時間和最小等待時間停士,每個請求會從這兩個時間間隔中隨機(jī)取一個時間等待挖帘,相當(dāng)用戶實際操作系統(tǒng)時每個動作的思考時間。若測試單個接口則對應(yīng)的值都設(shè)置為0即可恋技。如果Taskset類中定義了min_wait拇舀、max_weight則會覆蓋Locust子類中定義的值。單位ms蜻底,默認(rèn)值1000ms

  • HttpLocust子類中的stop_timeout屬性為執(zhí)行測試的時間骄崩,單位為s

  • HttpLocust子類中的weight為該類執(zhí)行的權(quán)重,當(dāng)有多個子類時生效朱躺,如WebsiteUser刁赖、WebsiteU兩個HttpLocust子類中weight值分別為3和1.

  • Locust默認(rèn)單機(jī)單進(jìn)程運行搁痛,此模式下并不能充分利用單機(jī)的多處理器长搀,可使用分布式運行,即開啟一個master鸡典,n個slave(n為處理器個數(shù))源请,master負(fù)責(zé)啟動Locust的web服務(wù)和任務(wù)分發(fā),不會產(chǎn)生壓力,slave主要負(fù)責(zé)產(chǎn)生壓力

運行模式:

no-web模式

no_web模式指在命令行中直接運行

locust -f load_test.py -c 1 -r 1 -n 1
  • -f 指定要運行的Locust性能測試文件
  • -c 指定模擬的并發(fā)用戶數(shù)
  • -r 指定每秒的啟動用戶數(shù)
  • -n 指定運行次數(shù)
  • -t 指定運行的時間谁尸,例如300s,1m,1h
    寫完腳本調(diào)試時可在該模式下運行

單機(jī)單進(jìn)程運行

locust -f load_test.py

分布式運行

分布式運行舅踪,有單機(jī)多進(jìn)程運行和多機(jī)多進(jìn)程運行兩種

locust -f load_test.py --master       master模式下啟動locust
locust -f load_test.py --slave         啟動一個locust slave節(jié)點,單機(jī)多進(jìn)程模式
locust -f load_test.py --slave --master-host=192.168.105.11    啟動一個locust slave節(jié)點良蛮,多機(jī)模式下 
no_web模式下運行
image.png
web模式
image.png
  • Number of users to simulate:需要模擬的虛擬用戶個數(shù)
  • Hatch rate (users spawned/second):啟動虛擬用戶的速率抽碌,每秒產(chǎn)生出多少個用戶數(shù)


    QQ圖片20171109190334.png
  • 顯示并發(fā)數(shù)、響應(yīng)時間决瞳、異常率货徙、每秒請求數(shù)等
  • reqs/sec(每秒請求數(shù))為根據(jù)最近2s請求數(shù)據(jù)計算得到的數(shù)據(jù),即瞬時值


    QQ圖片20171109190430.png
  • 顯示rps皮胡、響應(yīng)時間痴颊、并發(fā)數(shù)在整個測試運行中的走勢圖


    QQ圖片20171109190455.png
  • 顯示測試過程中出現(xiàn)的所有失敗的請求

Exceptions顯示測試過程中出現(xiàn)的異常
Download Date提供測試結(jié)果csv文件的下載

測試數(shù)據(jù):

  • locust子類中設(shè)置的數(shù)據(jù)是全局的,為list時屡贺,使用自增方式取數(shù)據(jù)蠢棱,并發(fā)運行時會出現(xiàn)取到的數(shù)據(jù)重復(fù)的情況,如果對數(shù)據(jù)唯一性有要求甩栈,使用python的queue隊列的數(shù)據(jù)結(jié)構(gòu)即可
  • taskset子類中設(shè)置的數(shù)據(jù)是局部的泻仙,即每一個虛擬用戶都會有一個屬于自己的這個變量

queue數(shù)據(jù)結(jié)構(gòu)

隊列形式

q=queue.Queue(maxsize=3)       先進(jìn)先出隊列
q.put(1)      向隊列中存數(shù)據(jù)
q.get()        向隊列中取數(shù)據(jù)
q.put_nowait()       相當(dāng)于q.put(1, block=False),當(dāng)q隊列滿了之后put會觸發(fā)queue.Full異常
q.get_nowait()       相當(dāng)與q.get(block=False),當(dāng)q隊列為空之后get會觸發(fā)queue.Empty異常
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谤职,一起剝皮案震驚了整個濱河市饰豺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌允蜈,老刑警劉巖冤吨,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異饶套,居然都是意外死亡漩蟆,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進(jìn)店門妓蛮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來怠李,“玉大人,你說我怎么就攤上這事蛤克∞囫” “怎么了?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵构挤,是天一觀的道長髓介。 經(jīng)常有香客問我,道長筋现,這世上最難降的妖魔是什么唐础? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任箱歧,我火速辦了婚禮,結(jié)果婚禮上一膨,老公的妹妹穿的比我還像新娘呀邢。我一直安慰自己,他們只是感情好豹绪,可當(dāng)我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布价淌。 她就那樣靜靜地躺著,像睡著了一般瞒津。 火紅的嫁衣襯著肌膚如雪输钩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天仲智,我揣著相機(jī)與錄音买乃,去河邊找鬼。 笑死钓辆,一個胖子當(dāng)著我的面吹牛剪验,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播前联,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼功戚,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了似嗤?” 一聲冷哼從身側(cè)響起啸臀,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎烁落,沒想到半個月后乘粒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡伤塌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年灯萍,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片每聪。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡旦棉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出药薯,到底是詐尸還是另有隱情绑洛,我是刑警寧澤,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布童本,位于F島的核電站真屯,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏巾陕。R本人自食惡果不足惜讨跟,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鄙煤。 院中可真熱鬧晾匠,春花似錦、人聲如沸梯刚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽亡资。三九已至澜共,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間锥腻,已是汗流浹背嗦董。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留瘦黑,地道東北人京革。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像幸斥,于是被迫代替她去往敵國和親匹摇。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,619評論 2 354

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