tl;dr

最近、ギョームで JMeter を触っているので、個人的にハマったこと等をメモしておく。

クラサバを利用する場合

JMeter は実際に負荷をかけるサーバー(JMeter サーバー)と結果を収集するサーバー(JMeter クライアント)のような構成で負荷試験を実施することが出来る。その際に以下の点に注意する。

  • スレッド数は Slave 数で割り算してシナリオに指定する(目標が 100 スレッドの試験を Slave 2 台で実施する場合にはシナリオのスレッド数には 50を設定する)
  • CSV データを利用する場合で各スレッドで読み込ませる値の重複を避けたい場合には slave 毎にデータを用意すること

以下、クラサバ構成のイメージ。

20160522170233

CSV データ

基本

JMeter ではリクエストパラメータ等を CSV ファイルから読み込むことが出来る。

  • CsvDataSetConfig はデフォルトでファイルの頭からデータを読み込む
  • ${__CSVRead(dummy_data.csv,0)} のように __CSVRead 関数を利用しても読み込むことが出来る
  • ランダムにファイルを読み込ませたい場合にはランダムにデータを生成するか、BeanShell を利用する

CsvDataSetConfig の Sharing Mode 設定による挙動の違い

以下のようなシナリオで検証。

パラメータ 備考
threads 10
ramp_up 1
loops 1
Thread Group 1
Sampler 2 HTTP サンプラーを 1 つの Thread Group に登録

以下のような結果となった。

パラメータ シナリオ内のパラメータ 挙動
All Threads shareMode.all 全てのスレッドグループで利用される(例:テスト計画内で冒頭から順番に読み込む = 全てのスレッドで異なる値がセットされる、但し、Sampler が 2 つの場合には Sampler 毎に冒頭から順番に読み込む)
Current Thread group shareMode.group スレッドグループで利用される(例:Sampler が 2 つの場合には Sampler 毎に冒頭から順番に読み込む)
Current Thread shareMode.thread 生成されるスレッドで同じ値が利用される(例:loops が 1 の場合には各 Sampler の各スレッドで同じ値が利用される)

以下はシナリオにアクセスさせたアプリケーションサーバーのログ。

  • All Threads
I, [2016-05-22T01:24:42.943456 #10]  INFO -- : {"endpoint":"01","param_id":"00000001"}
I, [2016-05-22T01:24:43.936219 #10]  INFO -- : {"endpoint":"01","param_id":"00000002"}
I, [2016-05-22T01:24:44.139027 #10]  INFO -- : {"endpoint":"02","param_id":"00000001"}
I, [2016-05-22T01:24:45.076087 #10]  INFO -- : {"endpoint":"01","param_id":"00000003"}
I, [2016-05-22T01:24:45.244973 #10]  INFO -- : {"endpoint":"02","param_id":"00000002"}
I, [2016-05-22T01:24:45.954286 #10]  INFO -- : {"endpoint":"01","param_id":"00000004"}
I, [2016-05-22T01:24:46.268197 #10]  INFO -- : {"endpoint":"02","param_id":"00000003"}
I, [2016-05-22T01:24:46.973422 #10]  INFO -- : {"endpoint":"01","param_id":"00000005"}
I, [2016-05-22T01:24:47.143580 #10]  INFO -- : {"endpoint":"02","param_id":"00000004"}
I, [2016-05-22T01:24:47.944595 #10]  INFO -- : {"endpoint":"01","param_id":"00000006"}
I, [2016-05-22T01:24:48.153880 #10]  INFO -- : {"endpoint":"02","param_id":"00000005"}
I, [2016-05-22T01:24:48.950102 #10]  INFO -- : {"endpoint":"01","param_id":"00000007"}
I, [2016-05-22T01:24:49.010407 #10]  INFO -- : {"endpoint":"02","param_id":"00000006"}
I, [2016-05-22T01:24:49.953918 #10]  INFO -- : {"endpoint":"01","param_id":"00000008"}
I, [2016-05-22T01:24:50.013803 #10]  INFO -- : {"endpoint":"02","param_id":"00000007"}
I, [2016-05-22T01:24:50.967745 #10]  INFO -- : {"endpoint":"01","param_id":"00000009"}
I, [2016-05-22T01:24:51.020484 #10]  INFO -- : {"endpoint":"02","param_id":"00000008"}
I, [2016-05-22T01:24:51.963473 #10]  INFO -- : {"endpoint":"01","param_id":"00000010"}
I, [2016-05-22T01:24:52.047907 #10]  INFO -- : {"endpoint":"02","param_id":"00000009"}
I, [2016-05-22T01:24:53.029975 #10]  INFO -- : {"endpoint":"02","param_id":"00000010"}
  • Current Thread group
I, [2016-05-22T01:23:46.286683 #10]  INFO -- : {"endpoint":"01","param_id":"00000001"}
I, [2016-05-22T01:23:47.281721 #10]  INFO -- : {"endpoint":"01","param_id":"00000002"}
I, [2016-05-22T01:23:47.352691 #10]  INFO -- : {"endpoint":"02","param_id":"00000001"}
I, [2016-05-22T01:23:48.288518 #10]  INFO -- : {"endpoint":"01","param_id":"00000003"}
I, [2016-05-22T01:23:48.348424 #10]  INFO -- : {"endpoint":"02","param_id":"00000002"}
I, [2016-05-22T01:23:49.391192 #10]  INFO -- : {"endpoint":"01","param_id":"00000004"}
I, [2016-05-22T01:23:49.392149 #10]  INFO -- : {"endpoint":"02","param_id":"00000003"}
I, [2016-05-22T01:23:50.413074 #10]  INFO -- : {"endpoint":"01","param_id":"00000005"}
I, [2016-05-22T01:23:50.583339 #10]  INFO -- : {"endpoint":"02","param_id":"00000004"}
I, [2016-05-22T01:23:51.408239 #10]  INFO -- : {"endpoint":"01","param_id":"00000006"}
I, [2016-05-22T01:23:51.605759 #10]  INFO -- : {"endpoint":"02","param_id":"00000005"}
I, [2016-05-22T01:23:52.304031 #10]  INFO -- : {"endpoint":"01","param_id":"00000007"}
I, [2016-05-22T01:23:52.475033 #10]  INFO -- : {"endpoint":"02","param_id":"00000006"}
I, [2016-05-22T01:23:53.305954 #10]  INFO -- : {"endpoint":"01","param_id":"00000008"}
I, [2016-05-22T01:23:53.372124 #10]  INFO -- : {"endpoint":"02","param_id":"00000007"}
I, [2016-05-22T01:23:54.310463 #10]  INFO -- : {"endpoint":"01","param_id":"00000009"}
I, [2016-05-22T01:23:54.371953 #10]  INFO -- : {"endpoint":"02","param_id":"00000008"}
I, [2016-05-22T01:23:55.316532 #10]  INFO -- : {"endpoint":"01","param_id":"00000010"}
I, [2016-05-22T01:23:55.378067 #10]  INFO -- : {"endpoint":"02","param_id":"00000009"}
I, [2016-05-22T01:23:56.387567 #10]  INFO -- : {"endpoint":"02","param_id":"00000010"}
  • Current Thread
I, [2016-05-22T01:22:03.892348 #10]  INFO -- : {"endpoint":"01","param_id":"00000001"}
I, [2016-05-22T01:22:04.883584 #10]  INFO -- : {"endpoint":"01","param_id":"00000001"}
I, [2016-05-22T01:22:04.960085 #10]  INFO -- : {"endpoint":"02","param_id":"00000001"}
I, [2016-05-22T01:22:05.899709 #10]  INFO -- : {"endpoint":"01","param_id":"00000001"}
I, [2016-05-22T01:22:05.951360 #10]  INFO -- : {"endpoint":"02","param_id":"00000001"}
I, [2016-05-22T01:22:06.891873 #10]  INFO -- : {"endpoint":"01","param_id":"00000001"}
I, [2016-05-22T01:22:06.965210 #10]  INFO -- : {"endpoint":"02","param_id":"00000001"}
I, [2016-05-22T01:22:07.895110 #10]  INFO -- : {"endpoint":"01","param_id":"00000001"}
I, [2016-05-22T01:22:07.959563 #10]  INFO -- : {"endpoint":"02","param_id":"00000001"}
I, [2016-05-22T01:22:08.899537 #10]  INFO -- : {"endpoint":"01","param_id":"00000001"}
I, [2016-05-22T01:22:08.960530 #10]  INFO -- : {"endpoint":"02","param_id":"00000001"}
I, [2016-05-22T01:22:09.907625 #10]  INFO -- : {"endpoint":"01","param_id":"00000001"}
I, [2016-05-22T01:22:09.965401 #10]  INFO -- : {"endpoint":"02","param_id":"00000001"}
I, [2016-05-22T01:22:10.905454 #10]  INFO -- : {"endpoint":"01","param_id":"00000001"}
I, [2016-05-22T01:22:10.974008 #10]  INFO -- : {"endpoint":"02","param_id":"00000001"}
I, [2016-05-22T01:22:11.951190 #10]  INFO -- : {"endpoint":"01","param_id":"00000001"}
I, [2016-05-22T01:22:12.112910 #10]  INFO -- : {"endpoint":"02","param_id":"00000001"}
I, [2016-05-22T01:22:13.038075 #10]  INFO -- : {"endpoint":"01","param_id":"00000001"}
I, [2016-05-22T01:22:13.235865 #10]  INFO -- : {"endpoint":"02","param_id":"00000001"}
I, [2016-05-22T01:22:14.226355 #10]  INFO -- : {"endpoint":"02","param_id":"00000001"}

ぱっと見は All ThreadsCurrent Thread group は同様の挙動に見えるが、All Threads は複数のスレッドグループが存在すると以下に挙動が変わる。(各 Thread Group に 1 つの HTTP サンプラーを設定 )

I, [2016-05-22T01:31:04.287215 #10]  INFO -- : {"endpoint":"02","param_id":"00000002"}
I, [2016-05-22T01:31:04.287686 #10]  INFO -- : {"endpoint":"01","param_id":"00000001"}
I, [2016-05-22T01:31:05.288151 #10]  INFO -- : {"endpoint":"01","param_id":"00000003"}
I, [2016-05-22T01:31:05.289218 #10]  INFO -- : {"endpoint":"02","param_id":"00000004"}
I, [2016-05-22T01:31:06.290228 #10]  INFO -- : {"endpoint":"01","param_id":"00000005"}
I, [2016-05-22T01:31:06.291241 #10]  INFO -- : {"endpoint":"02","param_id":"00000006"}
I, [2016-05-22T01:31:07.288733 #10]  INFO -- : {"endpoint":"01","param_id":"00000007"}
I, [2016-05-22T01:31:07.290312 #10]  INFO -- : {"endpoint":"02","param_id":"00000008"}
I, [2016-05-22T01:31:08.289742 #10]  INFO -- : {"endpoint":"01","param_id":"00000009"}
I, [2016-05-22T01:31:08.294290 #10]  INFO -- : {"endpoint":"02","param_id":"00000010"}
I, [2016-05-22T01:31:09.289464 #10]  INFO -- : {"endpoint":"01","param_id":"00000011"}
I, [2016-05-22T01:31:09.294437 #10]  INFO -- : {"endpoint":"02","param_id":"00000012"}
I, [2016-05-22T01:31:10.291579 #10]  INFO -- : {"endpoint":"01","param_id":"00000013"}
I, [2016-05-22T01:31:10.300185 #10]  INFO -- : {"endpoint":"02","param_id":"00000014"}
I, [2016-05-22T01:31:11.296709 #10]  INFO -- : {"endpoint":"01","param_id":"00000015"}
I, [2016-05-22T01:31:11.300298 #10]  INFO -- : {"endpoint":"02","param_id":"00000016"}
I, [2016-05-22T01:31:12.300593 #10]  INFO -- : {"endpoint":"01","param_id":"00000017"}
I, [2016-05-22T01:31:12.307913 #10]  INFO -- : {"endpoint":"02","param_id":"00000018"}
I, [2016-05-22T01:31:13.300271 #10]  INFO -- : {"endpoint":"01","param_id":"00000019"}
I, [2016-05-22T01:31:13.342417 #10]  INFO -- : {"endpoint":"02","param_id":"00000020"}

アサーション

  • JSON を返すような API サーバーを試験する場合には、ステータスコード以外にもアサーションでレスポンスボディをチェックすること

負荷が偏ったり、負荷が掛らない場合

ELB を利用しているアプリケーションに対して負荷を掛ける場合、負荷が偏ったり、負荷が掛らない場合がある。

www.slideshare.net

上記の資料にも記載されているが、ELB は負荷に応じてスケールしてくれるものの、スケールする際に IP が変わってしまう為、JMeter の DNS キャッシュを以下の何れかの方法で無効にする必要がある。(上記資料では 1 分に 1 回程度 DNS の再解決を行うようにとの記述がある(50 ページ目))

  • jmeter.properties に以下を追加
sun.net.inetaddr.ttl=0

するか、JMeter の起動オプションに以下を追加する。

-Dsun.net.inetaddr.ttl=0

ELB 利用のアプリケーションの負荷試験を行う場合には上記のオプションは必須だと思われる。

以上

メモでした。

元記事はこちら

個人的な JMeter FAQ