KAKEHASHI Tech Blog

カケハシのEngineer Teamによるブログです。

AWSの負荷テストソリューションを使ったGraphQLの負荷テスト

はじめに

こんにちは、LINE上で動くおくすり連絡帳 Pocket Musubi というサービスを開発している種岡です。 日頃もくもくと開発作業に勤しむ傍ら、ときどきユーザーからの生の声(良くも悪くも)が届くのは嬉しいものです。 サービスが成長している1つの証である一方で、ふと「サーバーへの負荷大丈夫なんだろうか?」と頭をよぎり心配になります。 この記事では、AWSが提案している負荷テストソリューションの使い方を紹介し、ボトルネックを早期発見および、安定的な運用につながればと思い筆を取りました。

AWSの分散負荷テストソリューションとは

AWSの公式より全体構成を抜粋しています。

AWSが用意するCloudFormationを利用すると上記のソリューションが数分でデプロイされ、すぐにテストを実施できる環境が用意できるという代物です。 ざっくりとまとめると以下のようになります。

  • 負荷テストのシナリオを登録できるコンソールがAmplifyでホストされいる
  • 負荷テスト実行するとFargateが立ち上がり、テストが終了すると自動的に停止してくれる
  • Fargateの中では Taurus というオープンソースのテスト自動化フレームワークが動いている

負荷テスト環境構築

  1. こちらのページにある AWSコンソールで起動するを選択します

  2. スタック作成画面はデフォルトの設定のままで次に進めます

  3. スタックの詳細画面では、後ほど利用するコンソールにアクセスするためのアカウント情報を登録します VPCの情報は既存のものと被らないように注意して進めます

  4. スタック作成後にデプロイが始まり、終了後、登録したメールアドレス宛にコンソール画面へのログイン情報が届きます

  5. コンソールにログイン後、ダッシュボードが表示されるので CREATE TEST からテストを作成します

  6. フォームに必要な情報を入力して、 RUN NOW を押します

    • Task Count は起動するDockerコンテナ数
    • Concurrency は同時接続数
    • Ramp Up はConcurrencyの値に達するまでの時間
    • Hold For は同時接続数を維持する時間 以下の設定だと、1分間(Ramp Up)で同時リクエスト数は1(Task Count x Concurrency)に達して、最大同時接続数の負荷を1分間(Hold For)維持する設定となります

  7. テスト実行中はFargateが立ち上がっている様子が確認できます

  8. テストが終了後に結果を確認できます

  9. テストの結果や実行したシナリオはS3に保存されています

以上でAWSの分散負荷テストソリューションの一連の動作が確認できました。

負荷テストのシナリオ作成

これまでは特定のエンドポイントに対しての負荷テストができることを見てきました。 次に、実際の利用シーンを想定したシナリオに対する負荷テストについて考えていきます。 AWSの負荷テストソリューションは、負荷テストツールである JMeter のシナリオを流用できるという特徴があります。 具体的には、JMeterで作ったシナリオを作り、以下のように、AWS負荷テストツール上でシナリオを読み込ませて実行できます。 よって、JMeterのシナリオ作成について見ていくことにします。

JMeterのインストール

Macの場合はHomebrewでインストールできます。

$ brew install jmeter

以下のコマンドでJMeterを起動できます。

$ jmeter

JMeterの設定

起動すると以下のような画面が表示されます。

まずは背景を Nimbus に変更します。 (DarculaだとJMeterのシナリオを保存できない不具合があるため)

ついでに言語も日本語にしておきます。

シナリオ作成

  1. スレッドグループの作成

  2. スレッドグループのスレッドプロパティを確認しておく 初期設定ではスレッド数やRamp-Up、ループ回数は 1 になっていることを確認

  3. GraphQL HTTP Requestの作成

    • サンプラーからGraphQL HTTP Requestを作成

    • ターゲットのエンドポイントに合わせてリクエストを調整

      • プロトコルは指定しないと HTTP になる
      • サーバー名またはIPパス に対象のエンドポイントの情報を入力
      • QueryタブやVariablesタブに適切なクエリとパラメーターを追加

    • HTTPヘッダーを追加

      • HTTPヘッダマネージャを追加

      • ヘッダーを追加 ヘッダーは個別に追加しようとしても上手く動かなかったので、事前に以下のようなテキストをクリップボードにコピーしておきます。 Accept-Encoding: gzip, deflate, br Content-Type: application/json Accept: application/json Authorization: aaaa

      • Add from Clipboard ボタンを利用することで画面に反映できます。

  4. 同じ要領でリクエストを追加を繰り返し、シナリオを作成します

テストシナリオの実行

  • 動作確認用にレポートを作成しておく

  • 実行ボタンを押し、負荷テストが実行できたかを確認する

  • 問題がなければテストシナリオを保存し、AWSの負荷テストソリューション上から参照することで実行できます

    • 負荷テストのシナリオはサービスの特徴を考慮し、よくある画面遷移のパターンを軸に複数検討しておくと良さそうです
      • 通常のアクセス量
      • ピーク時の3倍ぐらいのアクセス量
      • セールなどスパイクが想定されるイベントでの急激なアクセス

負荷テスト実行後の分析

AWS負荷テストソリューションで得られるレポートだけでは、原因を突き止めることはできません。 弊社では監視アプリケーションに Datadog を使っています。 アプリケーションとDatadogを連携させておくことで、スループットやレイテンシーが目標値に達しているかや、リクエスト内にボトルネックとなっている処理を特定するのに役立ちます。

おわりに

今回紹介したAWSの負荷テストソリューションは、あらかじめ用意されたCloudFormationを利用することで、すぐに環境構築され、負荷テストを開始できます。 また、JMeterの特徴である複数画面遷移のテストシナリオを実行できることも強みです。 サービスの成長と共に機能やアクセス量は増えていくため、安定した運用を目指し、定期的な負荷テストの実施でボトルネックを探すことが望ましいと思います。 その点、一度環境構築してしまえば、あとはJMeterでシナリオを拡張していくだけなので、定期的な負荷テストを実現できそうなところが魅力でした。