Stress Test with Locust written in Python


この記事は Brainpad Advent Calender 2019 2日目の記事になります

こんにちは@nissy0409240です
BrainPadでエンジニアをしています
2019年もあと一ヶ月を切りましたが
皆様いかがお過ごしでしょうか

今年はプライベートで東京ドームへ行くことが出来た
感動の一年でありました

東京ドームと言えば野球
野球と言えばピッチャーとバッターです
そんな前置きとは無関係に本エントリーでは
Pythonでシナリオを書ける負荷試験ツールLocustの基本的な機能を紹介させて頂きます

Locustとは

LocustとはGUIのインターフェースもついているPython製の負荷試験ツールです
他の負荷試験ツールと比較して一番大きい特徴はPythonでシナリオを書けることです
言葉遊びなようでもありますがPythonでシナリオを書かないといけないとも言えます

公式ドキュメント等の各種リンクはこちらになります

ちなみにLocustはバッタやイナゴという意味の英語です


イラストはトノサマバッタです

インストール方法

早速インストールしていこうと思います
インストールは下記コマンドを実行するだけです
※Macのローカル(Python3系)で動かすことを前提に進めます

$ brew install libev
$ python3 -m pip install locustio

実行後に$ locust --helpコマンドを実行し、ヘルプが表示されればインストール成功です


イラストはイナゴです

シナリオを作成

シナリオはPythonスクリプトに記述します。
記述するファイル名自体に制約は有りません。
ですが、起動時にファイル名の指定をしないとlocustfile.pyというファイル名のものが実行されるので
ファイル名の制約が無いのならlocustfile.pyというファイル名にすることをお薦めします。

以下がサンプルです

from locust import HttpLocust, TaskSet, task, between


class WebsiteTasks(TaskSet):
    @task
    def index(self):
        self.client.get('/')


class WebsiteUser(HttpLocust):
    task_set = WebsiteTasks
    wait_time = between(5, 15)

ちなみに受けるAPIサーバーはこんな感じです

from wsgiref.simple_server import make_server

import json


def api(environ, start_response):
    status = '200 OK'
    headers = [
        ('Content-type', 'application/json; charset=utf-8'),
        ('Access-Control-Allow-Origin', '*'),
    ]
    start_response(status, headers)

    return [json.dumps({'message':'hoge'}).encode("utf-8")]

with make_server('', 3000, api) as httpd:
    print("Serving on port 3000...")
    httpd.serve_forever()


イラストはショウリョウバッタです

起動

下記コマンドにて起動します

$ locust
[2019-12-01 00:56:13,884] locust.main: Starting web monitor at *:8089
[2019-12-01 00:56:13,885] locust.main: Starting Locust 0.9.0

上の例では何もオプションを着けて実行しておりませんが

-fオプションで実行したいシナリオが書かれたファイルを
-Hオプションで叩きたいエンドポイントを指定できます

デフォルトでLocustのプロセスは8089ポートで起動しますが
-Pオプションで起動時のポートを変更することが可能です

ちゃんと指定すると
このように起動します

$ locust -f locustfile.py -H http://localhost:3000 -P 8089
[2019-12-02 03:38:42,717] locust.main: Starting web monitor at *:8089
[2019-12-02 03:38:42,718] locust.main: Starting Locust 0.13.2


イラストはイナゴの佃煮です

テスト実行

起動後にブラウザからhttp://localhost:8089にアクセスすると
以下のようなGUIにアクセス出来ます


先程何気なく指定した叩きたいエンドポイントがデフォルトで設定されています


※起動時にHostを指定しない場合、Hostは空欄になります

空欄になっている設定項目があるので、以下の値を入力します
"Number of users to simulate" に100
"Hatch rate" に 1

それぞれの意味は以下の通りです

Number of users to simulate:何クライアント作成するか(最大で秒間何リクエストを送るかと同義)
Hatch rate:クライアントの作成スピード(毎秒ごと)
Host:接続先エンドポイント

今回はhttp://localhost:3000に対して1秒ごとに1クライアントづつ増やしながらリクエストを送信する
この時、最大でもクライアント数は100まで増やすこととする
という条件で実行します

入力後「Start Swarming」ボタンを押すとリクエストが実行されます

実行を終了させたい場合はブラウザの右上のSTOPボタンを押しましょう
押した後はSTATUSがSTOPPEDになり、終了したことが確認出来ます


イラストはバッタやイナゴの大群です

メトリクス

Chartsタブでメトリクスを見ることも出来ます


こちらは1秒ごとに1クライアントづつ増やし、最大100クライアントまで増えたらそのまま100クライアントでリクエストし続けた時のメトリクスです

続いて、リクエストに失敗した時はどのようになるか見ていきましょう
今回はAPIサーバーのプロセスを途中で停止してみようと思います





各タブにてこのように確認出来ます
失敗したリクエストの増え方やリクエスト全体に対する失敗の割合
Failuresタブではどのような理由で失敗したかも確認出来ます

また、Downloads Dataタブからは結果をダウンロードすることも可能です

ダウンロードしたファイルの中身はこのようになっています


イラストはバッタのキャラクターです

結び

以上、基本的な機能のみではございますがLocustの紹介をさせて頂きました
バッターのイラストとともにお別れです
最後までお付き合い頂きありがとうございました

参考

https://qiita.com/yamionp/items/17ffcc465272ad83c490
https://inside.pixiv.blog/east/5407
https://blog.htmlhifive.com/2015/08/14/web-server-load-testing-tools-2-locust/
https://docs.locust.io/en/stable/installation.html
https://docs.locust.io/en/stable/quickstart.html
https://co3k.org/blog/load-test-by-locust