asken テックブログ

askenエンジニアが日々どんなことに取り組み、どんな「学び」を得ているか、よもやま話も織り交ぜつつ綴っていきます。 皆さまにも一緒に学びを楽しんでいただけたら幸いです! <br> 食事管理アプリ『あすけん』 について <br> https://www.asken.jp/ <br>

はじめての負荷テストで学んだこと

はじめに

こんにちは。バックエンドエンジニアの齋藤です。

あすけんは1,100万人以上の会員様に利用いただいており、特に食事の時間帯にアクセスが集中します。そのため、ピーク時の大量リクエストにも対応できるかを確認する負荷テストが重要です。

今回は、「負荷テスト、JMeterって聞いたことはある…」という状態だった私が、半年間で得た知見を備忘を兼ねてまとめます。

負荷テストとは

AWSのこちらの記事が参考になります。

負荷テスト on AWS のすすめ ~ 第 1 回 : 負荷テストの全体像を理解しよう - builders.flash☆ - 変化を求めるデベロッパーを応援するウェブマガジン | AWS

上記で重要と感じた部分を抜粋します。

  • 負荷テストは高負荷をかけることでアプリケーションの性能を確認するテスト
  • 性能不足による機会損失やユーザーの離反を防ぐために行う
  • 「性能」には「処理量」と「処理時間」の2つの観点がある
  • 具体的には以下を確認する
    • ピーク性能
      • 予想されるスループット(単位時間あたりの処理量)をエラーやレスポンス遅延なく処理できるか
    • 限界性能
      • 目標のレスポンスタイム(リクエストの処理に要した時間・パーセンタイル値で集計)を遵守しながら、どれだけのスループットを捌けるか
      • 性能限界到達時のボトルネックがどこになるか

負荷テストの種類

AWSのこちらの記事が参考になります。

負荷テスト on AWS のすすめ ~ 第 2 回 : 負荷テストを計画しよう - builders.flash☆ - 変化を求めるデベロッパーを応援するウェブマガジン | AWS

今回は主に「②ピーク性能試験」について触れます。

ピーク性能試験

  • 想定する負荷比率・負荷量でオンライン負荷をかけ、目標性能を満たせるかを確認

どのくらい負荷をかけるか

今回はリアーキテクチャを行ったAPIがテスト対象でした。そのため、リアーキテクチャ前のAPIの現在のリクエスト数を基準に負荷量を決定しました。前述のようにあすけんは食事の時間帯に負荷が集中するため、1日のリクエスト数の平均ではなく、一番ピークの秒のリクエスト数を基準にしました。最大瞬間風速を基準にするイメージです。具体的には、メトリクスを確認してリクエストが多い日のピーク時間を特定し、その中で分間データ、秒間データと分解し、最もリクエスト数が多いものを採用しています。そして、採用したものに対して「× 60」をしたものを「rpm (request per minutes)」と定めました。

リクエストが多い日のピーク時間帯の「分」単位のメトリクス

ピークの分の「秒」単位のメトリクス

また、今回の対象APIは有料ユーザー向けの機能ですが、期間限定での無料開放を予定していました。そのため、無料開放時のリクエスト量も予想してもらいその想定でのテストも行いました。有料ユーザーと無料ユーザーの人数比から予測してもらったのですが、無料開放期間中に確認したところ、ほとんどその通りのリクエスト数となっており、このように予測すればよいのかと勉強になりました。

負荷をかけるツール

今回は詳しく記載しませんが、JMeter と AWS Distributed Load Testing (以下DLTとする) を利用して行いました。(別の機能の負荷テストにて構築済みでしたので、そのまま使わせてもらいました。)

一度JMeterをアップロードした後は、JMeterのシナリオを変更せずに、画面からタスク数とスレッド数を調整することで簡単に負荷量を変更できるのが便利でした。

以下に詳しい説明があります。

負荷テスト on AWS のすすめ ~ 第 3 回 : 負荷テストを準備・実施しよう - builders.flash☆ - 変化を求めるデベロッパーを応援するウェブマガジン | AWS

結果の確認

負荷をかけ終わったら結果を確認します。

まずは、DLT上でレスポンスタイムと、エラーが発生していないかを確認します。DLTの結果画面では、レスポンスタイムの平均の他、各パーセンタイルでのレスポンスタイムも表示してくれます。

例:「95 パーセンタイルで 1秒以内(全リクエストのうち 95% が 1秒以内に終了する)」

DLT結果画面

その後、逼迫した状況となっているリソースがないかを確認します。askenではNewRelicを利用しているため、NewRelicのダッシュボードを作り、一覧で確認できるようにしました。NewRelicに連携していないメトリクスは、AWS上で確認しました。(負荷テスト実施時は知らなかったのですが、AWSでもダッシュボードを作る機能があるため、今後はAWS側でチェックしたいメトリクスもダッシュボードを作って一覧で確認できるようにしたいです。)

もし結果を確認して、期待するレスポンスタイムに達していない場合は、どこで時間がかかっているかを確認します。NewRelicの Distributed tracing の機能は、どこで時間がかかっているかがわかりやすく、便利でした。

もしエラーが発生している場合は、ログからどこでエラーが発生しているか確認します。

性能以外で確認したポイント

性能以外に、以下も確認しました。

  • 可用性

スケールイン・スケールアウトやデプロイ時・データ入れ替え時などにも、システムが利用できる状態であるか。

  • 運用性

エラー発生時にログで原因の特定ができるかや、リソース逼迫時にアラートで気がつくことができるか。

  • 適切なスペックか

エラーやレスポンス遅延が起きておらずリソースも逼迫していなかった場合、逆に高すぎるスペックを指定して無駄なコストがかかっていないか。(各種利用率などを見て、少ししか利用していないものがある場合は、その部分を下げられるか検討するのがよいようですが、どのあたりが適切なのか見極めるのはまだ修行が必要と感じています。)

反省・注意点

実施してみて注意が必要と感じた点や反省点です。

実施中

  • 負荷をかけ始めて少ししたら状況を確認する

終わった後に確認したら、テストデータやユーザーあたりのリクエスト量上限などによりエラーが発生しており、再実施したことがありました。負荷をかけ始めて少ししたら、問題なく実行されているか確認するのが良さそうです。

  • 問題が起きた時に期間を決めて調査する。期間内に解決できなかったら他の方法を探る

負荷をかけた場合のみ、あるライブラリの利用箇所でエラーが発生した状況で、そのライブラリを使う前提での調査や試行錯誤に時間をかけてしまい、結局他の方法で実装しなおす方が早かったということがありました。負荷テストで発生する問題は複雑なことも多いので、調査の期間を決め、期間内に糸口が見つからない場合は別の方法を検討するのが良いようです。

  • 後から見てわかるように、実施日時・各リソースのスペック・負荷設定・結果を記録しておく

実施日時・各リソースのスペック・負荷設定・結果を記録しておくと、後から見た際もわかりやすいです。

メトリクス関連

  • SageMakerのCPU・GPU利用率
    • コア数 × 100%が上限になります。例えば、ml.g4dn.4xlarge のインスタンスを使っている場合、CPU: 16, GPU:1 のため、CPUの利用率の範囲は 0% ~ 1600% になります。AWSの「モニタリング」を使って確認している場合、「情報」で各メトリクスの説明を見ることができます。

  • JVMã‚„OpenSearchのメモリ利用率

JVMではリクエスト数に応じて徐々にメモリ利用率があがるわけではなく、最初にJVM引数で指定されたサイズを一括で確保します。そのため、メモリ利用率だけではなくヒープ領域の割り当ても確認する必要があります。OpenSearchでもJVMを利用しているため、メモリ利用率はリクエストがない時でも高い値になっていることがあります。メモリ利用率ではなく、以下を確認する方がよいようです。

・VM メモリプレッシャー
・CPU 使用率
・空きストレージ領域

参考:

JavaのGCの仕組みを整理する #Java - Qiita

Amazon OpenSearch Service で高い sysMemoryUtilization をトラブルシューティングする | AWS re:Post

OpenSearchの本番運用に向けて知っておきたいこと

  • OpenSearchの検索レイテンシー

AWSに問い合わせを行ったところ、CloudWatch メトリクスの 検索レイテンシー(SearchLatency )はリクエスト〜レスポンスまでの時間ではないとのことだったので注意が必要です。(リクエスト〜レスポンスまでの時間 = クエリがクエリフェーズで費やした時間 + フェッチフェーズの時間 + キューで費やした時間 + ネットワークレイテンシー からなるとのことですが、そのうちクエリフェーズで費やした時間 だけを表しているとのことです。)

その他

  • 試験条件が本番環境と近い条件になっているか確認する

テストデータの偏りによりキャッシュが使われ、想定する負荷をかけられていないことがありました。テストデータを作成する前に、利用するリソースにキャッシュがあるのか、ある場合は何単位でどれくらいの時間キャッシュが効くのかを確認する必要がありました。その他、リクエスト内容やDBデータ量、ユーザー数などが本番想定に近い状態になっているかも確認が必要でした。

  • 新しいライブラリを使う場合は、負荷に耐えられるか早めに確認する

通常負荷テストは、実装・結合テスト完了後、総合テストとしてリリースに近い段階で行うことが多いですが、あるライブラリを利用した時に負荷をかけた場合のみ時折エラーが発生し、解決できずに結局ライブラリを使わない方法で再実装することになったことがありました。新しいライブラリを使う場合は、選定時に負荷に耐えられるかをできるだけ早めに検証した方が良いと感じました。

おわりに

半年間で他のメンバーの方にも教えてもらいながら色々学びましたが、まだまだ学ぶことがありそうです。効率的に負荷テストを行なって安心して安定運用できるようにしていきたいです。 あすけんの成長スピードは毎年あがっており、2024年3月に累計会員数1,000万人を突破してから約6カ月後には1,100万人となりました。多くの会員様に使っていただくサービスを支える難しさとともに、大量のリクエストを捌くサービスならではのやりがいも感じています。

askenではエンジニアを絶賛募集中です。ぜひお気軽にご連絡ください!

hrmos.co