Python
PR

負荷テストツールLocustのインストールと実行

saratogax
記事内に商品プロモーションを含む場合があります

先日、負荷テストの話題になって聞き慣れないツールの名前が出たので調べてみました。

※本記事は Locust 0.8(Python 2)時代の内容です。

現行の Locust 1.0 以降ではパッケージ名(locustiolocust)と API が大きく変わっています。現行版の書き方は記事末尾にまとめました。

負荷テストのツールと言えば、簡易的なもので「Apache Bench」、もう少し凝ったことをやろうとして「JMeter」というイメージでした。

今回は、Python のコードでシナリオが記述できる「Locust」のインストール手順と実行方法を紹介します。

イナゴ?バッタ?の大群が襲ってくる負荷テストツール

「負荷試験にイナゴを使ってみたいんだよね」

そんな一言がこの話題の発端でした。

知らない人は「イナゴ」てググっていいのか、「175」でググるべきなのか迷うところですが、後者はもしかすると 175R を知ってる世代だけでしょうか。

要は「Locust」のことなのですが、「ローカスト」や「ルーカスト」などと呼んでいる人がいるようです。
(まあ、純粋に英語ですよね)

Locustの特徴

冒頭にもチラっと書きましたが、以下の特徴を持った負荷試験ツールです。

・シナリオがPythonで書ける
・分散テストができる
・WebのUIから負荷試験ができる

そういえば、数年前に Web の UI を持った負荷試験ツールを触ったことがあるような記憶が蘇ってきました。

もしかすると見たことのある UI かもしれないと早く画面が見たくなりますが、まずは試してみます。

Locustのインストール

Python のツールなので、pip コマンドでインストールをします。

pipコマンドの確認

pip コマンド自体は Lets’ Encrypt を同じサーバで利用しているので既に入っていました。

$ pip -V

pip 9.0.3 from /usr/lib/python2.7/dist-packages (python 2.7)

インストール実行

早速、locust のインストールです。

$ pip install locustio

You are using pip version 9.0.3, however version 18.0 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

最後に警告が出ましたが、pip のバージョンってこんなに差異があるの?

アップグレードして Let’s Encrypt の証明書更新ができなくなるのが嫌なので別のサーバで試みます。

別サーバでpipのアップグレード

無理にアップグレードする必要はないかもしれませんが、気になるので pip のアップグレードをしてから locust のインストールをすることにします。

$ pip install --upgrade pip

Installing collected packages: pip
Found existing installation: pip 9.0.3
Uninstalling pip-9.0.3:
Successfully uninstalled pip-9.0.3
Successfully installed pip-18.0

アップグレードが完了してバージョンが 18.0 になりました。

$ pip -V

pip 18.0 from /usr/lib/python2.7/dist-packages/pip (python 2.7)

再度Locustのインストール実行

そのまま pip をアップグレードしたサーバで locustio をインストールします。

$ pip install locustio

cloud-init 0.7.6 requires argparse, which is not installed.
cloud-init 0.7.6 requires cheetah, which is not installed.
cloud-init 0.7.6 requires oauth, which is not installed.
cloud-init 0.7.6 requires PrettyTable, which is not installed.
cloud-init 0.7.6 requires pyserial, which is not installed.
Cannot uninstall 'chardet'. It is a distutils installed project and thus we cannot accurately determine which files belong to it which would lead to only a partial uninstall.

警告なしでスムーズにいくかなと期待しましたが、今度は 6 個のエラーが出力されましたorz

この時点で、無理にアップグレードするんじゃなかったと少々の後悔・・・。

仕方ないので足りないパッケージのインストールをして、chardet のエラーを解決してから再度 locustio のインストールをします。

まずは、パッケージのインストールから。以下の 5 つのパッケージをインストールします。

$ pip install argparse cheetah oauth PrettyTable pyserial

最後にエラーの内容通り chardet を手動で削除します。

$ rm -f /usr/lib/python2.7/dist-packages/chardet-2.0.1.egg-info

$ rm -rf /usr/lib/python2.7/dist-packages/chardet

今度はエラーなくインストール完了です。

$ pip install locustio

バージョンを確認すると 0.8.1 となっています。まだ 1 を超えないのか・・・。

$ locust -V

Locust 0.8.1

Locustの実行

早速、使ってみたいと思いますが、Locust の Web UI の画面は8089 番ポートで待ち受けます。

AWS のセキィリティグループを触ってポートを開けるのが嫌だったので、nginx でリバースプロキシすることにしました。

ざっくり、こんな感じで設定ファイルを作って適当なドメインを振っておきます。
(何かのサブドメインとかでも)

気休めで Basic 認証でもしておきます。

server {
    server_name locust.example.org;
    auth_basic "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Authorization "";
    location / {
        proxy_pass http://127.0.0.1:8089;
    }
}

Locust の設定ファイルは「locustfile.py」というファイル名にしておくとデフォルトの設定ファイルとして読み込んでくれます。

設定内容は、トップページとリンク先のページに順番にアクセスする単純な画面遷移とします。

$ vi locustfile.py

from __future__ import absolute_import
from __future__ import unicode_literals
from locust import HttpLocust, TaskSet, task
class TaskSet1(TaskSet):
@task
def index(self):
self.client.get("/")
@task
def page(self):
self.client.get("/hoge/fuga")
class Wp(HttpLocust):
task_set = TaskSet1
min_wait = 1000
max_wait = 1000

これで Locust を起動して待ち受けてみます。

$ locust -H https://example.com

簡単に上記コマンドを説明すると、-H オプションで負荷を掛けたい相手先のホストを指定しています。

詳しくはヘルプを見てください。locustfile.py 以外の設定ファイルを使いたい場合は -f で指定します。

$ locust -h

Usage: locust [options] [LocustClass [LocustClass2 ... ]]
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

Locustの画面にアクセスしてテスト開始

では、nginx で設定した locust.example.org にアクセスしてみます。

問題がなければ、以下の設定が表示されます。

負荷テストツールLocustのインストールと実行

やはりこのツール、何年か前に Python 好きなエンジニアの人が使っていて紹介されたものでした。

このシンプルな画面は見覚えがあります。

ちなみに、設定項目は以下の通りです。

Number of users to simulate:クライアントの数
Hatch rate:クライアントの生成速度

今回はシンプルに 1 ユーザから始め、1 秒ごとに 1 ユーザずつ増加させていくことにしました。

負荷テストツールLocustのインストールと実行

これだと平均のレスポンス時間も短いですね。しかも、サイト側は nginx のキャッシュ利かせていますからね。

Max(ms)が 115 になっているアクセスはキャッシュが効いていない初回アクセスだったのかも。

負荷テストツールLocustのインストールと実行

設定を変更して負荷を上げる

画面上部の赤いストップボタンで停止し、ステータス付近の「New test」からユーザ数や増加数を変更してテストが開始できます。

今度は、5 ユーザから始まり毎秒 5 ユーザ増やしてみます。

負荷テストツールLocustのインストールと実行

やはりワードプレス相手でもキャッシュが効いていると速いですね。

この程度なら余裕で捌けます。

そして「100 / 100」で設定して秒間 100 にしても全く問題ありません。

キャッシュしちゃってるだけに、静的なページが返るだけですからね。

でもワードプレスの負荷軽減にページキャッシュは大きく貢献していることがわかります。

「500 / 500」の設定から、ある程度アクセスを捌けてはいるものの、徐々にロードアベレージが増加してきました。

負荷テストツールLocustのインストールと実行

現行版(Locust 1.0 以降)での書き方

Locust 1.0(2020 年)で大きく変わった点を、現行版に置き換えてまとめておきます。

まず、パッケージ名が locustio から locust に変わり、Python 3.6 以上が必要です。

$ pip install locust

クラスは HttpLocustHttpUser、待機時間は min_wait / max_waitwait_time = between(...)、タスクは TaskSet を介さず @task をメソッドに直接付けます。

from locust import HttpUser, task, between

class Wp(HttpUser):
    wait_time = between(1, 1)

    @task
    def index(self):
        self.client.get("/")

    @task
    def page(self):
        self.client.get("/hoge/fuga")

起動コマンドは同じく locust -H https://example.com で、Web UI もデフォルトで 8089 番ポートです。

なお、Web UI の「Hatch rate」は 1.0 で「Spawn rate」に名称変更されています。

まとめ

Locust をサーバにセットアップして、簡単な負荷を特定のサイトにかけてみました。

実は今回、同じサーバのサイトに対して行ったので、実際はもう少し状況は変わってくるハズです。

本来ならリモートからやらないとあまり意味もないですしね。

また、シナリオが Python で書けるので、もっと凝ったシナリオも作れそうです。

ABOUT ME
saratoga
saratoga
フリーランスエンジニア
仕事にも趣味にも IT を駆使するフリーランスエンジニア。技術的な TIPS や日々の生活の中で深堀りしてみたくなったことを備忘録として残していきます。
記事URLをコピーしました