ちょっと話題の記事

負荷テストをサーバーレスで実現するServerless-artilleryを試してみた

Webシステムの負荷テストツール選定にお悩みではないでしょうか。私は悩んでいました。 今回はサーバーレスで負荷テストを実施するServerless-artilleryを紹介します。
2020.10.26

こんにちは。
ご機嫌いかがでしょうか。
"No human labor is no human error" が大好きなネクストモード株式会社 の吉井です。

今回はサーバーレスで負荷テストを実施できる Serverless-artillery を紹介します。
Lambda 関数からテスト対象 URL に対して事前に定義した回数、期間、パターンで負荷をかけます。
テストサーバーを EC2 で起動し管理することは、それなりに手間ですし、テストが長期間になればコストも無視ができなくなります。
その点 Lambda なら実行回数分のコストなので安心感はあります。

負荷テストの実施

Serverless-artillery を使用して負荷テストを行っています。
作業端末から Serverless-artillery 実行環境をデプロイします。お手元に Linux サーバーをご用意ください。


https://github.com/Nordstrom/serverless-artillery より引用

IAM ユーザー作成

Serverless-artillery をデプロイするための IAM ユーザーを用意します。
私の環境では以下のポリシーを割り当てました。
ご自身の環境に合わせて増減をお願いします。

  • AWSLambdaFullAccess
  • IAMFullAccess
  • AmazonSNSFullAccess
  • AWSCloudFormationFullAccess

IAM ユーサーを作成したらアクセスキーを作成してダウンロードしておきます。

AWS CLI

AWS CLI をインストールします。インストール方法は以下を参照ください。
AWS CLI のインストール

AWS CLI の初期設定をします。
前の手順で作成したアクセスキー情報を入力します。

aws configure

AWS Access Key ID [None]: Your Key
AWS Secret Access Key [None]: Your Access Key
Default region name [None]: ap-northeast-1
Default output format [None]:

Serverless-artillery インストール

まずは Node.js をセットアップします。

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
. ~/.nvm/nvm.sh
nvm install node

Node.js がインストールされたことを確認します。

node -e "console.log('Running Node.js ' + process.version)"

Serverless-artillery をインストールします。
私が試した際は、Serverless が最新(v2.xx)だと動かなかったので、あえて古い v1.40.0 をインストールしています。

FEATURE REQUEST: Serverless ^2.0.0 Compatibility

npm install -g serverless@1.40.0
npm install -g serverless-artillery

インストールされたことの確認です。

slsart --version

テストスクリプトの作成

ご自身の環境に合わせたテストスクリプトを作成します。
作業用ディレクトリを作成してその配下にスクリプトを作成します。

mkdir work_dir
cd work_dir

slsart script

「script.yml」というファイルが出来ているはずです。
このファイルを編集します。

  • target : テスト対象 URL
  • duration : テスト期間(秒)
  • arrivalRate : 秒間アクセス数
config:
  target: http://TESTURL/
  phases:
    - duration: 5
      arrivalRate: 10
scenarios:
  - flow:
      - get:
          url: "/"

デプロイ

slsart deploy を実行するとテストリソースがデプロイされます。
CloudFormation を見ると「serverless-artillery-xxxx」というスタックが作成されているのが確認できます。

slsart deploy --stage test1 --region=ap-northeast-1

負荷テスト実施

slsart invoke コマンドを実行するとテスト開始です。

slsart invoke --stage test1 --region=ap-northeast-1

テスト先として用意した apache アクセスログを tail してみます。

tail -f logs/access_log

sourceIPaddress - - [26/Oct/2020:04:32:24 +0000] "GET // HTTP/1.1" 200 76 "-" "Artillery (https://artillery.io)"
sourceIPaddress - - [26/Oct/2020:04:32:24 +0000] "GET // HTTP/1.1" 200 76 "-" "Artillery (https://artillery.io)"

負荷テスト結果

slsart invoke コマンドの結果が出力されました。
latency はミリ秒です。min,max,median,p95,p99 が表示されています。
私のお気に入りは95パーセンタイルです。

{
  "timestamp": "2020-10-26T04:32:29.482Z",
  "scenariosCreated": 50,
  "scenariosCompleted": 50,
  "requestsCompleted": 50,
  "latency": {
    "min": 2.2,
    "max": 46.1,
    "median": 2.4,
    "p95": 18,
    "p99": 46.1
  },
  "rps": {
    "count": 50,
    "mean": 9.52
  },
  "scenarioDuration": {
    "min": 4,
    "max": 202.9,
    "median": 4.4,
    "p95": 21,
    "p99": 202.9
  },
  "scenarioCounts": {
    "0": 50
  },
  "errors": {},
  "codes": {
    "200": 50
  },
  "matches": 0,
  "customStats": {},
  "phases": [
    {
      "duration": 5,
      "arrivalRate": 10
    }
  ]
}

Large Test

Serverless-artillery は短期間のテスト結果なら標準出力に表示しますが、長期のテストは標準出力には表示されません。
結果が表示されないテストは意味がなく困ってしまいます。
長期のテストでも結果が確認できるように CloudWatch メトリクスへ出力します。

追加手順

前の手順で使用した同じディレクトリ配下にて以下のコマンドを実行します。
.js や .json といったファイルが大量にダウンロードされるはずです。

slsart configure

CloudWatch プラグインをインストールします。

npm install artillery-plugin-cloudwatch --save

ファイル編集

script.yml の config ブロックに以下の plugins 以下3行を追記します。
namespace の値は任意の文字列に置き換えてください。

duration と arrivalRate を増やして長期間かつ大量リスエストのテストへ変更しています。

config:
  target: http://TESTURL/
  phases:
    - duration: 600
      arrivalRate: 50
  plugins:
    cloudwatch:
      namespace: "serverless-artillery-loadtest1"

再デプロイ

再度デプロイします。

slsart deploy --stage test1 --region=ap-northeast-1

負荷テスト実施

再度負荷テストを実施します。

slsart invoke --stage test1 --region=ap-northeast-1

CloudWatch メトリクス

CloudWatch メトリクスを見てみましょう。
script.yml で指定したネームスペースでメトリクスが出力されています。

image

CloudWatch Logs Insight

グラフだけでは物足りないこともあるかと思います。
その場合は CloudWatch Logs を検索します。
ロググループ名 「/aws/lambda/serverless-artillery-xxxx」で保管されています。

CloudWatch Logs Insight で以下のクエリを発行します。

fields @message
| filter (@message like /p95/ and @message like /^(?!.*NaN).+$/)
| parse @message /p95: (?<tile>.*)/
| avg(tile)

「p95」を置き換えれば希望の値を取得できると思います。

  • min : レイテンシーの最小値
  • max : レイテンシーの最大値
  • median : レイテンシーの中央値
  • p95 : レイテンシーの95パーセンタイル
  • p99 : レイテンシーの99パーセンタイル

テストスクリプト

script.yml を書き込んでいくと様々な状況のテストが実施可能です。
GET / POST / PUT / PATCH / DELETE 各リクエストやヘッダー、Basic 認証、Cookies など一通り揃っていると思います。

細かい記述方法は artillery ドキュメントを参照ください。

Test Script Reference

Testing HTTP

負荷テスト以外のモード

Serverless-artillery には負荷テスト以外に2つのモードがあります。

Acceptance mode

script.yml に記述した内容を一度だけ実行します。
CI/CD パイプラインの一部に組み込むことが可能です。

Acceptance mode の実行コマンドは以下です。

slsart invoke -a --stage <your-unique-stage-name>

詳細は以下を参照ください。
Acceptance mode

Monitoring mode

読んで字のごとくです。
Serverless-artillery を URL 死活監視に使用します。

SNS メール通知やモニタリングの一時停止などの手順が書かれています。
Monitoring mode

まとめ

いかがでしたでしょうか。
Web システムの負荷テストをサーバーレスで実施しました。
仮想サーバーから実施すると仮想サーバー自身の負荷や限界があり、思った結果が出ない経験をされた方もいらっしゃると思います。
また、単純に横並びで仮想サーバーを増やすのも苦痛ですし、テスト結果を集計する作業も辛いものがあります。
今回紹介した Serverless-artillery で効果的なテストを実施してみてはいかがでしょうか。

参考

Serverless-artillery
Test Script Reference
Testing HTTP

以上、吉井 亮 がお届けしました。