負荷試験ツールLocustをCLIで実行する。

Locustを用いて手軽に負荷をかける。

## 参考
https://docs.locust.io/en/stable/index.html

## 手順
pipが使用できる前提ですが、まずはlocustをインストールします。

```Python
# locustのインストール
pip install locust
```

次にテストシナリオを記述するlocustfile.pyを作成します。

```Python:locustfile.py
from locust import HttpUser, TaskSet, task
import datetime

class UserBehavior(TaskSet):
    @task
    def print_time(self):

        print(datetime.datetime.now())

class WebsiteUser(HttpUser):
    tasks = {UserBehavior:1}

```

これだけで準備完了。一度動かしてみます。
![画面収録 2021-06-06 16.28.45.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684883/13ca06ed-49bd-12d5-697f-59949b0da71e.gif)

なんとなく動いていそうなことがわかります。
ただ、これだとどのくらいの負荷をかけているか分からないので、負荷量を指定して実行します。
wait_time = constant_pacing(1)を追加し、スリープ時間を設定します。
これでにより毎秒１回のペースで実行できていそうです。

```Python:locustfile.py
from locust import HttpUser, TaskSet, task, constant_pacing
import datetime

class ClientBehavior(TaskSet):
    # wait_timeを設定することでスリープ時間を任意の値に設定可能
    wait_time = constant_pacing(1)
    @task
    def print_time(self):
        '''
        関数に任意の名前をつけることができ、任意の処理を記述します。
        今回は動作テストのため、現在時刻を表示します。
        '''
        print(datetime.datetime.now())

class WebsiteUser(HttpUser):
    tasks = {ClientBehavior:1}

```

```
# 実行結果
$ locust

 Name                                                          # reqs      # fails  |     Avg     Min     Max  Median  |   req/s failures/s
--------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------
 Aggregated                                                         0     0(0.00%)  |       0       0       0       0  |    0.00    0.00

2021-06-06 16:54:39.810798
2021-06-06 16:54:40.814379
 Name                                                          # reqs      # fails  |     Avg     Min     Max  Median  |   req/s failures/s
--------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------
 Aggregated                                                         0     0(0.00%)  |       0       0       0       0  |    0.00    0.00

2021-06-06 16:54:41.816906
2021-06-06 16:54:42.814922
2021-06-06 16:54:43.813107
 Name                                                          # reqs      # fails  |     Avg     Min     Max  Median  |   req/s failures/s
--------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------
 Aggregated                                                         0     0(0.00%)  |       0       0       0       0  |    0.00    0.00

2021-06-06 16:54:44.811236
2021-06-06 16:54:45.816294
 Name                                                          # reqs      # fails  |     Avg     Min     Max  Median  |   req/s failures/s
--------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------
 Aggregated                                                         0     0(0.00%)  |       0       0       0       0  |    0.00    0.00

2021-06-06 16:54:46.812859
2021-06-06 16:54:47.816211

```

このままでは負荷試験と呼べるほど負荷をかけることができないので、
複数インスタンス立ち上げて実行することも当然可能である。
オプションとして、-uで立ち上げるインスタンス数、-rで毎秒何インスタンス立ち上げるか、
-tで負荷をかける時間を設定することができる。

```
$ locust -u 5 -r 5 -t 180s

 Name                                                          # reqs      # fails  |     Avg     Min     Max  Median  |   req/s failures/s
--------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------
 Aggregated                                                         0     0(0.00%)  |       0       0       0       0  |    0.00    0.00

2021-06-06 17:58:01.236927
2021-06-06 17:58:01.445396
2021-06-06 17:58:01.650598
2021-06-06 17:58:01.857148
[2021-06-06 17:58:02,063] masayaPC.local/INFO/locust.runners: All users spawned: WebsiteUser: 5 (5 total running)
2021-06-06 17:58:02.065378
2021-06-06 17:58:02.242371
2021-06-06 17:58:02.450938
2021-06-06 17:58:02.656181
2021-06-06 17:58:02.862731
2021-06-06 17:58:03.070850
```

上記の場合、１秒間で５インスタンス立ち上がり、各インスタンスが毎秒１回処理を行なっている。

実行時の引数として与える以外に、設定ファイルを作成し実行時に設定ファイルを指定することでも
上記と同様のことを行うことができる。

```
# locust.conf

locustfile = locustfile.py
headless = true
host = http://example.com
users = 1
# spawn-rate: 1秒あたりに増加する秒間ユーザ数
spawn-rate = 1
run-time = 60s
loglevel = DEBUG
```

## おわりに
LocustはPythonでテストシナリオを記述するため、Webサイトの負荷テスト以外にも
boto3などを利用すればAWSサービスに負荷をかけることも可能ですね。