Apache JMeterで負荷テストする時の設定やテスト後のチェック項目

業務でApache JMeterを使ったAPIの負荷テストを行なったので、その流れを共有。

## 目次
・負荷テストの概要
・Apache JMeterダウンロード・起動
・テストプラン作成
・デバッグ（JMeter）
・負荷テスト実行
・テスト後のチェック項目

実行した端末、バージョン情報はこちら。
Mac OSX El Capitan 10.11.5
Apache JMeter 5.1.1


## 負荷テストの概要
テストの対象は、イベント来場者の受付を行うAPI。来場者が現場に押し寄せても、システムが問題なくリクエストをさばけることを検証する。
来場者は来場証を持参し、会場にてQRコードを受付で読み取ってもらい、読み取り時にAPIをたたく。
実行頻度は20rq/sec、実行時間は90minで実施。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276559/8a8f3eab-0fea-0e7b-7f68-d8d606dc5edc.png)


## Apache JMeterダウンロード・起動
[公式サイト](https://jmeter.apache.org/download_jmeter.cgi)から現時点の最新版である5.1.1をダウンロードし、ダウンロードしたzipファイルを展開。
binフォルダ直下のjmeterファイルを実行するとJMeterの画面が表示される。
![jmeter_初期画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276559/e015a322-1628-ef4e-5d48-bc2c847140b0.png)
同時にターミナル上に注意事項が表示される。
```Don't use GUI mode for load testing ! only for Test creation and Test debugging.```

GUIモードはテストケースの作成やデバッグのために使用し、負荷テストの実行には使わないでとの事。（[1.0.2 Load Test running](http://jmeter.apache.org/usermanual/get-started.html#load_test_running)）

また、画面を日本語表示したい場合は、bin/jmeter.properties　で以下設定をする。

```
 #language=en
 language=ja
```

## テストプラン作成
負荷テストを行うために、Apache JmeterのGUIで以下の設定を行う。

スレッドグループ
サンプラー（HTTPリクエスト）
ユーザパラメータ
HTTP認証マネージャ

- [スレッドグループ](http://jmeter.apache.org/usermanual/test_plan.html#thread_group)

テストプランを作成するとき、まずはスレッドグループを作成する。スレッドグループの単位がテストプランの単位になるので、もし来場者の検索や申込処理も同時並行して処理を行うシナリオで負荷テストをしたい場合は、それぞれの処理毎にスレッドグループを作成する事になる。今回は受付APIだけのテストなので、1つのスレッドグループを作成。

最初に表示されているTest Plan（テスト計画）から、「追加 > Threads(Users) > スレッドグループ」を選択し、赤枠部分を設定。
![スレッドグループ設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276559/3289eed7-fd83-c9a6-d470-0a3b6a82e9d3.png)
名前：スレッドグループの名称
スレッド数：生成するスレッドの数
Ramp-Up期間(秒)：指定したスレッド数を生成するのにかける時間
ループ回数：1スレッドの中でテストを繰り返し実行する回数
Delay Thread creation until needed：選択

5,400スレッドを5,400秒かけて生成、1スレッドの中で20回ループさせるように設定することで、20rq/sec の頻度で90分間かけてAPI実行するようにしている。

[Delay Thread creation until needed](https://jmeter.apache.org/usermanual/best-practices.html#sizing_threads) は、スレッドが開始されるまでスレッドの生成を遅らせる事ができるもので、スレッド数が多い時に設定するのがベストプラクティスだそう。Ramp-Up期間で生成時間を設定するが、これを選択しないとテスト開始と同時に全スレッドが生成される意味にとれる。




- [サンプラー](http://jmeter.apache.org/usermanual/test_plan.html#samplers)（HTTPリクエスト）
 
スレッドグループから、「追加 > サンプラー > HTTPリクエスト」を選択し、赤枠部分で送信するリクエストの情報を設定。今回で言うと受付APIのリクエスト情報をここに記載。
＊特に送信先のWEBサーバ情報を間違えていないか良く確認。絶対にテスト対象でないサーバに負荷をかけない。
![HTTPリクエスト設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276559/bbfe05ec-67a3-04f2-ccd6-8e175ccc9566.png)
サンプラーは1つのテストケースにあたり、リクエストを送信しレスポンスを待つ役割をもつ。複数のサンプラーを作成したときは、表示されている上から順に実行される。
名前のbarcode_noに「${barcode_no}」と記載されているのは変数であり、リクエスト毎に異なる値をセットする。（後述）


- [ユーザパラメータ](http://jmeter.apache.org/usermanual/component_reference.html#User_Parameters)
 
スレッドグループから、「追加 > 前処理 > ユーザパラメータ」を選択。
![スクリーンショット 2019-08-29 8.05.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276559/82edb8f3-3590-5d7b-2c10-9181e20a601c.png)
名前：パラメータの名前（barcode_no）　※サンプラーで記載した名前と同じもの
ユーザー1：パラメータの値を記載したテキストファイルのパス（${__StringFromFile(/Users/example/barcode_list.txt)}）

テキストファイルには以下のように記述する。

```
# barcode_list.txtの記載内容
1001
1002
1003
1004
(略)
```

テストケース毎に${barcode_no}の値として、10001、10002が順に格納され、最後のパラメータまで到達すると、また最初の1001から格納されていく。ユーザ1の欄に記載している「[__StringFromFile](https://jmeter.apache.org/usermanual/functions.html#__StringFromFile)」はApache Jmeter内で定義されている関数で指定されたファイルを読み込み、1行ずつ値を読み込み結果を返す。


- HTTP認証マネージャ（Basic認証設定）

スレッドグループから、「追加 > 設定エレメント > HTTP認証マネージャー」を選択し、赤枠部分でBasic認証情報を記載。
![Basic認証設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276559/9d180904-a1fa-6e47-bba7-bd23e34e95bd.png)
ここまででテストプランの作成は完了したので、保存をする。

## デバッグ（JMeter）
ここまで行った設定をJMeterが正しく認識して動くか確認するため、リスナを作成する。

スレッドグループから、「追加 > リスナー」で以下をそれぞれ選択。

- [結果をツリーで表示](http://jmeter.apache.org/usermanual/component_reference.html#View_Results_Tree)：各リクエスト、レスポンスデータを確認できる
- [結果を表で表示](http://jmeter.apache.org/usermanual/component_reference.html#View_Results_in_Table)：各リクエストの開始時間、応答時間を確認できる
- [統計レポート](http://jmeter.apache.org/usermanual/component_reference.html#Summary_Report)：Throughput、Error率などの集計結果を確認できる

リスナを作成後、テストを開始すると各リスナに結果が順次表示されていく。ここで意図した実行頻度、リクエスト・レスポンスデータかどうかを確認する。リスナは結果の確認に便利だが、中には多くのリソースを消費してしまうものもあるため（上記だと結果をツリーで表示）、それらはデバッグで使用するに留める。


## 負荷テスト実行
デバッグまで済んで問題なければ、いよいよ負荷テストを実行する。上記で作成したテストプランをコマンドラインで実行する。（GUIでは実行しない）

```
bin/jmeter -n -t <テストプランファイルパス> -l <テストレポートファイル出力パス>
```
-n：コマンドラインモードで実行する
-t：実行したいテストプランを含むJMXファイルを指定

他のオプションは[こちら](http://jmeter.apache.org/usermanual/get-started.html#non_gui)

テストを完了すると、レポートファイルが出力されるので、それをJMterのリスナー画面で読み込み、「テスト後のチェック項目」で確認を行う。
![スクリーンショット 2019-08-17 21.58.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276559/a597b378-89b0-b475-3aed-cbebec7b12aa.png)


## テスト後のチェック項目


- リクエスト頻度は計画値通りか（今回ならば20rq/sec）

　→ JMeterの統計レポートの「Throughput」やWEBサーバのアクセスログで確認

- レスポンスステータスが200以外のものがないか

　→ JMeterの統計レポートの「Error」が0である事、もしくは結果ファイルのステータスコードが200のみである事を確認

- レスポンスタイムは許容時間内か

　→ JMeterの結果を表で表示の「SampleTime」が想定時間内であることを確認

- 監視ツールでアラートは出ていないか

　→ Mackerelなどのアラート有無を確認

- サーバリソースに余裕はあったか（WEB・DBサーバのCPU・メモリなど）

　→ Mackerelなどでリソース使用状況を確認

- API側にエラーは発生していないか

　→ WEB・DBサーバ、アプリケーションのログを確認

- スロークエリは発生していないか

　→ DBのログを確認