Artillery 入門メモ

性能試験の話をすることがよくあるですが、この数年、負荷がけツール事情(?)に追いつけていない気がしたので、これを機に最近よく使われているものは何なのかなと調べていました。その調査の中でよさそうだった 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 

artillery.io

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

シナリオには重みをつけることもできるようなので、どこかで試します。

artillery.io

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 に入門しました。他にも使いたい機能があるので、おって試していきたいと考えています。