「Distributed Load Testing on AWS ソリューション」で負荷テストを内製化してみた

グラフと積み木 負荷イメージ

みなさま、こんにちは。じつげつです。

私はソニー・ミュージックソリューションズに所属するエンジニアで、普段はWebアプリケーションの要件定義やテスト、負荷試験、性能試験を担当しています。

今回は私が担当している仕事の中から、ここ最近取り組んでいる負荷試験、性能試験の内製化について紹介します。

なぜ負荷試験・性能試験を内製化しなければならないのか

ソニー・ミュージックソリューションズは、ソニーミュージックグループが提供するさまざまなWebサービスの開発・運用を行っています。当然、これらのサービスの運用を開始するにあたり、あらかじめ負荷試験や性能試験を行う必要があるのですが、従来はそのための環境作りを外部の協力会社にお願いしていました。しかし、近年は、以下のような理由から、内製化に向けた取り組みをスタートしています。

  1. 高負荷になる案件が増えてきて、負荷試験の重要性が高まっている ここ最近は月2~3回程度の頻度で発生している
  2. 外部への依頼はコストも時間もかかってしまう
  3. 短納期の案件が多く、短時間での負荷試験実施が求められている 依頼から3日~1週間で結果が欲しいといったかなりの短納期のものがある

現在も運用サイトが増え続けていて、さらに大規模な施策についても相談が来続けている状況から、スピーディーな負荷試験の実施が必要不可欠な状況となってきているのです。

Distributed Load Testing on AWS ソリューションを試してみた

上記の理由からどうにか負荷試験を内製化できないか模索していたところ、AWS(Amazon Web Service)からAWS上での分散負荷テストを手軽に自動化できる新機能「Distributed Load Testing on AWS ソリューション」の発表があり、これを負荷試験・性能試験に使えないかと考え、利用を開始しました。

Distributed Load Testing on AWS ソリューションの構成図(AWS公式から引用)
Distributed Load Testing on AWS ソリューションの構成図(AWS公式から引用)

このツールを導入しようとした理由ですが、大きく、以下の3つが挙げられます。

  1. 環境構築がAWS CloudFormationでテンプレート化されていたため容易だった
  2. 指定した負荷量に応じてコンテナが起動するので、サーバー台数の調整をあまり意識せずとも負荷がかけられる
  3. JMeterのシナリオが取り込めるため、シナリオ作成も容易

上記の中でも、2のサーバー台数の調整を意識しなくてよい点が特に大きなメリットだと考えています。今までは、JMeterを利用する際、外部の協力会社に依頼をし、試験の要件をまとめ、そこから負荷量を出し、それに応じてAmazon EC2の台数を決めるなど、大変な手間と時間がかかっていました。対して、このツールでは並列ユーザー数を決めれば、それに応じてコンテナ台数を設定するだけでよいので、かなりの時間短縮につながります。

Distributed Load Testing on AWS ソリューションの利用手順

Distributed Load Testing on AWS ソリューションは、以下のような流れで利用します。

1.シナリオ作成

シナリオはJMeterで作成して、作成したシナリオ、ユーザーリストなどをzip化する

※zipファイルはファイル名を日本語にすると試験実行時にエラーになるので注意。

JMeter画面

2.Distributed Load Testingでテストを作成する

Distributer Load Testingの設定画面
Distributer Load Testingの設定画面

3.負荷の規模を決める

Task Count:起動するECSのコンテナの台数

Concurrency:コンテナ1台当たりの仮想ユーザー数

4.試験時間の設定

Ramp Up:コンテナが立ち上がるまでの時間

Hold For:負荷をかけ続ける時間

5.シナリオの取り込み

1で作成したシナリオをアップロードする。

Test FileをJMeterにしファイルをアップロード。

6.試験実行

Run Nowを押すと試験が開始される。

実行後、エラーになる場合は、Amazon CloudWatch Logsにログが吐き出されているので、そこを確認することで、およその原因が把握可能です(我々のケースでは取り込んだシナリオファイルのファイル名が日本語だったために、取り込みエラーになっているといったことがありました)。

また、連続して試験をする場合は、直前の試験の影響(CPU使用率やメモリ、DBコネクション等)がなくなってから実施をするようにしてください。実際、そこの確認を怠って正しい結果が得られなかったことがありました。

試験結果はどうやって確認するのか

試験結果についてはDistributed Load Testingの試験結果と、負荷をかけたサービスのCloudWatchを確認して、リソース状況やレスポンスタイム、エラー数などを確認しています。

テスト結果のイメージテスト結果のイメージテスト結果のイメージ
テスト結果のイメージ

結果についてはDistributed Load Testingの結果画面に加えて、負荷をかけた環境のCloudWatchでリクエスト数や、オリジンのレイテンシー、5xx系エラーの数、EC2やAmazon RDSのCPU使用率、DBのコネクション数、Amazon DynamoDBのスロットルの有無などを確認して負荷をかけた際の影響度合いを確認しています。

これらリソース状況を見て、ボトルネックとなっている可能性がある個所をまずは判断しています(たとえばECサイトの購入遷移でRDSのWriterノードのCPU使用率が100%で高止まりしている場合、カート追加などの処理が遅くなっているのではないか、など)。

その後並列ユーザー数を変えてかける負荷量を変えたり、RDSのスペックや、EC2の台数を変更したりすることで、影響度合いの変化を確認します。

なお、弊社の場合、これらの結果が出そろったタイミングには、すでに開発がアウトソーシングされているため、結果を開発ベンダーに共有して改善策を検討していきます。

なんにせよ、JMeterのシナリオさえ作成できてしまえば、あとは画面に従って設定するだけで負荷がかけられるので、かなり簡単に負荷試験ができるようになりました。

導入の成果と今後について

Distributed Load Testingの導入によって、これまで頭を悩ませていた負荷試験がかなり手軽に実施できるようになりました。あと、これは実際に利用を始めてみてからわかったのですが、Distributed Load Testingは1回の負荷試験でかかる利用料が数ドルと安く、コスト面でも大きなメリットがあります。

現状はECサイトの購入遷移や、ログインAPIに対する負荷試験など、シンプルな試験が中心のため、今後はWebSocketなどを利用したサービスの負荷試験も内製化できるようにしていきたいと考えています。 また、手軽に実施できる点から、APIの追加などをした際の非機能要件の性能面のテストなどにも流用できそうです。さらに、最近実施している負荷試験では同じシナリオを複数回実行することが多く、今の状態だと、手動で都度実行する形になっているので、Amazon EventBridgeなどをうまく活用して、スケジュールを設定するだけで自動実行できるようにならないかも検討しています。

将来的には内製化だけではなく、外部に依頼していた会社とも協力してこのツールを利用するなど、試験実施の選択肢も広げられればと思っています。