性能試験の話をすることがよくあるですが、この数年、負荷がけツール事情(?)に追いつけていない気がしたので、これを機に最近よく使われているものは何なのかなと調べていました。その調査の中でよさそうだった Artillery を試しに使ってみたので、その作業メモを残したいと思います。
導入
$ npm install -g artillery
するだけです。なお、私は例によって AWS Cloud9 環境を新しく作って試しています。
クイックに実行する例
10人の仮想ユーザーが20のリクエストを投げる例
Getting Started にも載っているものです。
$ artillery quick --count 10 -n 20 *URL*
実行結果です。10秒おきの実行状況と、最後にサマライズされた結果が表示されるようです。
$ artillery quick --count 10 -n 20 https://artillery.io/ Started phase 0, duration: 1s @ 00:36:23(+0000) 2020-08-09 Report @ 00:36:27(+0000) 2020-08-09 Elapsed time: 4 seconds Scenarios launched: 10 Scenarios completed: 10 Requests completed: 200 Mean response/sec: 51.81 Response time (msec): min: 121.3 max: 609.1 median: 123.5 p95: 279.3 p99: 505.5 Codes: 200: 200 All virtual users finished Summary report @ 00:36:27(+0000) 2020-08-09 Scenarios launched: 10 Scenarios completed: 10 Requests completed: 200 Mean response/sec: 51.68 Response time (msec): min: 121.3 max: 609.1 median: 123.5 p95: 279.3 p99: 505.5 Scenario counts: 0: 10 (100%) Codes: 200: 200
N秒間で M rps の負荷をかけ続ける例
$ artillery quick --duration N -rate M *URL*
実行結果
$ artillery quick --duration 30 -rate 20 https://artillery.io/ ...(省略) All virtual users finished Summary report @ 04:54:17(+0000) 2020-08-09 Scenarios launched: 600 Scenarios completed: 600 Requests completed: 600 Mean response/sec: 19.73 Response time (msec): min: 373.8 max: 394.4 median: 381.4 p95: 386.7 p99: 391.1 Scenario counts: 0: 600 (100%) Codes: 200: 600
20 * 30 = 600 リクエストが飛んでいることが分かりますね。
シナリオベースで実行する例
YAML ファイルにシナリオを書き、テストを実行することができます。
$ artillery run test.yml
GET リクエストを1回送るシナリオを、毎秒30リクエスト、20秒に渡って実行する例
まずは先程 CLI で行ったものと同じ N秒間で M rps の負荷をかけるシンプルな例です。
config: target: 'https://xxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev' phases: - duration: 20 # 何秒間実行するか arrivalRate: 30 # 秒間のシナリオ実行回数 scenarios: - flow: # ここに1シナリオで行う処理を記載する - get: url: "/translate?input_text=hoge"
実行結果です。合計600回のリクエストが送れていることが分かります。
...(省略) All virtual users finished Summary report @ 01:09:14(+0000) 2020-08-09 Scenarios launched: 600 Scenarios completed: 600 Requests completed: 600 Mean response/sec: 29.37 Response time (msec): min: 207.7 max: 1244.8 median: 268.7 p95: 319 p99: 434.6 Scenario counts: 0: 600 (100%) Codes: 200: 600
GET リクエストを1回、POST リクエストを1回送るシナリオを、毎秒30リクエスト、20秒に渡って実行する例
flow
の部分はユーザーのオペレーションを配列で記載することができます。GET リクエストに続いて、POST リクエストも投げる例です。
config: target: 'https://xxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev' phases: - duration: 20 arrivalRate: 30 scenarios: - flow: # ユーザーの1度の操作を配列で定義できる - get: url: "/translate?input_text=hoge" - post: url: "/translate"
実行結果です。シナリオの消化数は600ですが、リクエストの総量が1,200になっていることが確認できます。
...(省略) All virtual users finished Summary report @ 04:22:17(+0000) 2020-08-09 Scenarios launched: 600 Scenarios completed: 600 Requests completed: 1200 Mean response/sec: 58.77 Response time (msec): min: 2.4 max: 1466.3 median: 166 p95: 382.7 p99: 1344.8 Scenario counts: 0: 600 (100%) Codes: 200: 1200
シナリオには重みをつけることもできるようなので、どこかで試します。
Phase によって負荷を変えるシナリオを書く
徐々にリクエスト数が増えていくテストをしたいことがあると思います。その場合は phases
に配列で条件を書くことができるので、最初の N 秒はこれくらい、次の M 秒はこれくらい、と書くことが可能です。
config: target: 'https://xxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev' phases: - duration: 20 # 最初の20秒間は、 arrivalRate: 20 # 20 rps で負荷をかける - duration: 20 # 次の20秒間は、 arrivalRate: 40 # 40 rps で負荷をかける scenarios: - flow: - get: url: "/translate?input_text=hoge"
実行結果は下記の通りです。10~20秒の10秒間は200リクエストが、30~40秒の10秒間は401リクエストが来ていることが分かります。最終的には、2020+4020=1,200のリクエストが届いています。途中、微妙に増減はありますが、期待通りの結果になっているようです。
...(省略) Report @ 04:26:43(+0000) 2020-08-09 Elapsed time: 20 seconds Scenarios launched: 200 Scenarios completed: 200 Requests completed: 200 Mean response/sec: 20.02 Response time (msec): min: 233 max: 503.3 median: 266.4 p95: 342.4 p99: 443.2 Codes: 200: 200 ...(省略) Report @ 04:27:03(+0000) 2020-08-09 Elapsed time: 40 seconds Scenarios launched: 400 Scenarios completed: 401 Requests completed: 401 Mean response/sec: 40.04 Response time (msec): min: 210 max: 450.2 median: 265.7 p95: 338.4 p99: 423.2 Codes: 200: 401 ...(省略) All virtual users finished Summary report @ 04:27:03(+0000) 2020-08-09 Scenarios launched: 1200 Scenarios completed: 1200 Requests completed: 1200 Mean response/sec: 29.69 Response time (msec): min: 210 max: 503.3 median: 266.5 p95: 329.5 p99: 417.9 Scenario counts: 0: 1200 (100%) Codes: 200: 1200
rampTo を使って徐々に負荷をかける
rampTo
を使うことで、段階的に増やして最終的にはこの値にしてね、という表現も簡単に書くことができます。
config: target: 'https://xxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev' phases: - duration: 60 arrivalRate: 0 # このシナリオ量(仮想ユーザー数)からスタートし、 rampTo: 60 # 最終的にこの量になる scenarios: - flow: - get: url: "/translate?input_text=hoge"
結果は、下記のようになります。最初の10秒は 0 + 1 + .. + 9 = 45 くらいになっていますね。厳密な動きはドキュメントの "How do ramps work?" に書かれていますが、よほど厳密にやりたいシーン以外ではこれで十分だなと思いました。
Started phase 0, duration: 60s @ 04:37:14(+0000) 2020-08-09 Report @ 04:37:24(+0000) 2020-08-09 Elapsed time: 10 seconds Scenarios launched: 48 Scenarios completed: 46 Requests completed: 46 Mean response/sec: 5.9 Response time (msec): min: 241 max: 1311.5 median: 288.3 p95: 595.3 p99: 1311.5 Codes: 200: 46 Report @ 04:37:34(+0000) 2020-08-09 Elapsed time: 20 seconds Scenarios launched: 153 Scenarios completed: 150 Requests completed: 150 Mean response/sec: 15.56 Response time (msec): min: 162.1 max: 1307.5 median: 270.2 p95: 386.3 p99: 1267 Codes: 200: 150 ...(省略) All virtual users finished Summary report @ 04:38:16(+0000) 2020-08-09 Scenarios launched: 1808 Scenarios completed: 1808 Requests completed: 1808 Mean response/sec: 30.05 Response time (msec): min: 162.1 max: 1311.5 median: 266.7 p95: 335.9 p99: 481.2 Scenario counts: 0: 1808 (100%) Codes: 200: 1808
まとめ
Artillery に入門しました。他にも使いたい機能があるので、おって試していきたいと考えています。