TL;DR
負荷試験時に活用できる、AWS上にJMeterクラスタを立てるテンプレートを作りましたので、ご利用下さい!!
はじめに
開発推進グループのbbrfkr(ビビリフクロウ)こと、斎藤です。
WebサイトやAPIの負荷試験をする際、皆様はどのようなツールを利用されていますでしょうか? シンプルにab
コマンド? Web上からLoad Impact
で行う手もあります…
私が担当しているプロジェクトではApache JMeterを利用しています。「ユーザの行動を想定するとこのAPIを叩いてから次にそのAPIを叩いて…」といったシナリオテス卜をXMLフォーマットでコード化しておくこともでき、またHTTPステータスコードやレスポンスタイム、スループットといった情報がまとめられたレポートも吐き出してくれるので、大変重宝しています。
JMeterではクライアント-サーバ構成でクラスタを組むことで、大規模な負荷試験を巨大なCPU・メモリリソースを一つ用意するのではなく、容易に調達可能なCPU・メモリリソースをたくさん用意することで実現することができます。しかし、複数のサーバを人が逐一用意していくのは効率的ではありません…
そこでJMeter ClusterをAWSに自動構築するコードを作成することにしました。折角なので他のプロジェクトや同様の悩みを抱えている方々の助けになればと思い、使い回しが可能なテンプレートの形にしてあります。
使い方
事前準備
以下のURLでコードを公開しておりますので、まずはコードをgit clone
してください。
git clone
したら、pip
およびpipenv
コマンドで依存パッケージをインストールします。なお、pythonバージョンは3.8でのみ動作確認しております。
$ pip install pipenv $ pipenv install $ pipenv shell
次にリポジトリ直下で設定ファイルのサンプルをコピーします。
$ cp variables.yaml.sample variables.yaml
コピーした設定ファイルvariables.yaml
内の変数に値を入力していきます。各変数の意味は以下の通りです。
変数名 | 説明 |
---|---|
jmeter_region | JMeterクラスタをデプロイするAWSリージョン |
jmeter_vpc | JMeterクラスタをデプロイするVPC |
jmeter_subnet | JMeterクラスタが所属するサブネットID |
jmeter_allowed_ip | JMeterクラスタに属するインスタンスにSSHする際の接続許可ソースIP(CIDRで記載。なおパブリックIPが付与されるかはVPCの設定に依存しますので、プライベートサブネットでご利用の場合は、生成されたインスタンスにアクセス可能な踏み台サーバのIPを指定して下さい) |
jmeter_ami_id | JMeterクラスタのインスタンスに利用するAMI ID (Amazon Linux 2で動作確認済み。RedHat系OSのみ利用可能) |
jmeter_client_instance_type | JMeterクライアント(サーバに負荷試験指示を出すインスタンス)のインスタンスタイプ |
jmeter_server_instance_type | JMeterサーバ(実際に負荷試験対象に負荷をかけるインスタンス群)のインスタンスタイプ |
jmeter_key_pair | JMeterクラスタのキーペア |
jmeter_servers_count | JMeterサーバの数 |
jmeter_install_version | インストールするJMeterのバージョン(例: 5.2.1) |
jmeter_heap_initial_size | JMeterサーバの初期ヒープメモリサイズ (パラメータXms に与えられます) |
jmeter_heap_max_size | JMeterサーバの最大ヒープメモリサイズ (パラメータXmx に与えられます) |
jmeter_max_meta_space_size | JMeterサーバのMetaspace領域の最大値 (パラメータXX:MaxMetaspaceSize に与えられます) |
jmeter_max_open_file | オープン可能なファイル数の上限 (ulimit -n コマンドの引数に与えられます) |
また、本コードは内部的にboto3を使用しますので、対象AWSアカウントに対するクレデンシャルを環境変数やAWS CLIのaws configure
コマンドで予め与えておいてください。環境変数で与える場合はリポジトリ直下のファイル.env.sample
を以下のコマンドでコピーし、値を入力します。
$ cp .env.sample .env
その後、sourceコマンドで環境変数を読み込ませます。
$ source .env
以上で、JMeterクラスタをデプロイする準備は完了です。
JMeterクラスタの起動
依存パッケージと変数の準備が完了していれば、JMeterクラスタのデプロイは以下のコマンドを実行するだけです!
本コードではsceptreとtroposphereというツールを利用して、CloudFormationスタックを作成することでデプロイを実現しています。
$ sceptre --var-file ./variables.yaml launch cluster
デプロイし終わったJMeterサーバ群をデプロイするスタックを見ると、出力
の欄にJMeter実行時に与えるremote_hosts
プロパティが生成されているので、こちらをJMeter実行前にクライアントに設定すればサーバ群に接続して負荷試験を実施できます。
負荷試験が終わったら…
負荷試験が完了しレポート等を取得して、JMeterクラスタが不要になった際は以下のコマンドでクリーンアップすることができます。
$ sceptre --var-file ./variables.yaml delete cluster
構成
構成というほど大した内容ではありませんが、本コードの実行と負荷試験実施をイメージした図を以下のとおり示しておきます。
sceptre
コマンドを実行してJMeterクライアント用のStackとJMeterサーバ群用のStackを作ります- JMeterサーバ群用のStackの
出力
からremote_hosts
プロパティを読取り、JMeterクライアントに設定します - 負荷試験シナリオを作成するか、既存シナリオをダウンロードし、JMeterクライアントに配置します
jmeter
コマンドにて負荷試験を実施し、負荷試験対象システムに負荷を掛けます
まとめ
負荷試験実施用のクライアントは、JMeterでそれなりの負荷をかけようとすると意外とスペックを要求されます。AWSなどのパブリッククラウドを利用することで一時的に多くのコンピュートリソースを手軽に用意することができ、試験が終わって不要になればそれらを迅速かつ簡単に破棄することができます。今回のようにリソースの用意と破棄を自動化すれば、さらに効率的に負荷試験を実施できますので是非お試しいただければ幸いです。