ECS Fargateで負荷テストツールLocustを動かしてAPIに負荷をかけてみた

はじめに

業務で負荷テストツール「Locust」を使う機会があり、AWS ECS Fargate上でLocustを動かして、APIに負荷をかける検証をやってみました。

Locustを使えばPythonで簡単に負荷テストのシナリオを書けるんです。
さらにECS Fargateで動かすことで、サーバー管理不要で大規模な負荷テストも可能になります。
私も初めて使ってみたので、一つ一つ丁寧に解説したいと思います!

目次

この記事でわかること

  • Locustとは何か
  • ECS Fargateで負荷テストを実行するメリット
  • Dockerイメージの作成方法
  • ECSでの実行方法
  • 負荷テストの結果の見方

前提条件

  • AWSアカウントを持っている
  • Dockerの基本的な知識がある
  • Pythonの基礎知識がある(読めればOK)

Locustとは?

Locustは、Pythonで書かれたオープンソースの負荷テストツールです。

Locustの特徴

  • Pythonで書ける: 複雑なシナリオもPythonコードで表現できる
  • WebUIが使いやすい: ブラウザから負荷テストの状況をリアルタイムで確認できる
  • 分散実行が可能: 複数のワーカーで大規模な負荷テストができる
  • 軽量: 1台のマシンで数千ユーザーをシミュレートできる

なぜECS Fargateで動かすのか?

メリット

  1. サーバー管理不要: EC2インスタンスの管理が不要
  2. スケーラブル: 必要に応じてタスク数を増やせる
  3. コスト効率: 使った分だけの課金
  4. 再現性: Dockerイメージで環境を固定できる

構成

テスト対象APIの準備(API Gateway + Lambda)

負荷テストの対象となるAPIを用意します。

Lambda関数とAPI Gatewayの作成

Lambda関数とAPI Gatewayを作成します。

Lambda関数の準備

API Gatewayの準備

方法1: SAMテンプレートを使用
デプロイ
方法2: CloudFormationテンプレートを使用
デプロイ

エンドポイントURLの取得

出力例: https://abc123.execute-api.ap-northeast-1.amazonaws.com

Locustテストシナリオの作成

負荷テストのシナリオをPythonで作成します。
locustfile_api_test.pyを作成

ポイント解説

  • HttpUser: HTTP/HTTPSリクエストを送るユーザーの基底クラス
  • @task(数値): 負荷テストで実行するタスクを定義。数値は実行頻度の重み(3:2:1の比率で実行)
  • wait_time: リクエスト間の待機時間(実際のユーザー行動をシミュレート)
  • on_start: 各ユーザーの初期化処理(後述)

on_startメソッドについて

今回のシナリオでは使用していませんが、認証が必要なAPIをテストする場合に重要です。

使用例:ログイン認証が必要な場合

on_startの用途

  • ログイン処理
  • 認証トークンの取得
  • テストデータの準備
  • セッションの初期化

Dockerイメージの作成

次に、Locustを動かすDockerイメージを作成します。
Dockerfileを作成

requirements.txtを作成

ローカルでの動作確認

ECSにデプロイする前に、ローカルで動作確認しましょう。

WebUIが表示されたら成功です!

ECRにイメージをプッシュ

セキュリティグループ設定

Locust WebUIにアクセスするためのセキュリティグループを設定します。

ポート プロトコル 送信元 用途
8089 TCP 自分のIP/32 WebUI

⚠️ セキュリティ上の注意

  • 本番環境では、必ず特定のIPアドレスに制限してください
  • 社内ネットワークからのアクセスの場合は、会社のIPレンジを指定しましょう

ECS環境の構築

ECSタスク定義の作成

task-definition.jsonを作成

ECS FargateでLocustを動かす準備が出来ました。

負荷テストの実行

WebUIを使った実行

  1. ECSタスクのパブリックIPを確認
  2. ブラウザで http://ECSのパブリックIPアドレス:8089 にアクセス
  3. 以下を入力:
    • Number of users: 100(同時接続ユーザー数)
    • Spawn rate: 10(1秒あたりに追加するユーザー数)
  4. 「Start swarming」ボタンをクリック

ヘッドレスモード(WebUIなし)での実行

自動化したい場合は、ヘッドレスモードが便利です。
タスク定義のcommandを以下に変更:

  • -u: ユーザー数
  • -r: 増加率(spawn rate)
  • -t: テスト実行時間

負荷テスト結果確認

負荷テストを実行した結果、以下のような結果を確認できました。

負荷試験の結果を、僕の良き相棒の、Amazon Qに分析してもらいました。

負荷テスト結果分析レポート


📊 総合評価: A+ (優秀)

指標 結果 評価 基準
失敗率 0% 🟢 優秀 < 1%
平均応答時間 25.96ms 🟢 優秀 < 100ms
95パーセンタイル 41ms 🟢 優秀 < 500ms
スループット 51.6 RPS 🟢 高性能 -

🔍 詳細分析

テスト結果サマリー
Type Name # Requests # Fails Median (ms) 95%ile (ms) 99%ile (ms) Average (ms) Min (ms) Max (ms) Average size (bytes) Current RPS Current Failures/s
GET /api/users 1,269 0 23 42 64 25.61 16 318 118 27 0
POST /api/users 440 0 22 40 75 26.09 17 300 61 9.5 0
GET /api/users/1 814 0 22 41 72 26.43 16 377 57 15.1 0
Aggregated - 2,523 0 22 41 66 25.96 16 377 88.38 51.6 0
1. 応答時間パフォーマンス
  • 中央値: 22ms (50%のリクエストが22ms以内)
  • 95パーセンタイル: 41ms (95%のリクエストが41ms以内)
  • 99パーセンタイル: 66ms (99%のリクエストが66ms以内)
  • 最大値: 377ms (一時的なスパイクあり)
2. エンドポイント別パフォーマンス

結果: 全エンドポイントで一貫した高性能を実現

3. スループット分析
  • 総RPS: 51.6 req/s
  • 総リクエスト数: 2,523
  • 実行比率: GET:POST:GET詳細 ≈ 3:1:2 (設計通り)
  • データ転送: 平均88.38 bytes/request

🎯 ベンチマーク比較

項目 今回結果 一般的な目標 達成率
応答時間 25.96ms < 200ms 87%改善
95%ile 41ms 99.9% 100%達成
失敗率 0% < 1% 完全成功

📈 スケーラビリティ予測

現在の性能から推定される処理能力:

  • 1分間: 約3,100リクエスト
  • 1時間: 約186,000リクエスト
  • 1日: 約450万リクエスト
  • 月間: 約1.35億リクエスト

⚠️ 注意点と改善提案

1. 最大応答時間のスパイク

問題: 377msの最大応答時間

  • 原因: Lambda冷却起動の可能性
  • 対策:
    • Provisioned Concurrency設定
    • メモリ増加 (128MB → 256MB)
2. 負荷レベル

現状: 比較的軽い負荷での結果

  • 提案: より高負荷でのテスト実施
3. 監視強化

推奨設定:

  • CloudWatch メトリクス追加
  • X-Ray トレーシング有効化
  • カスタムメトリクス設定

🚀 次のステップ

短期的改善 (1-2週間)
  1. Lambda最適化

    • メモリ設定: 128MB → 256MB
    • タイムアウト: 30秒 → 15秒
    • 環境変数最適化
  2. 高負荷テスト実施

    • 同時ユーザー数: 100-500
    • 実行時間: 30分
    • 段階的負荷増加
中期的改善 (1-2ヶ月)
  1. Provisioned Concurrency導入
  2. API Gateway キャッシュ設定
  3. CloudFront導入検討
長期的改善 (3-6ヶ月)
  1. 分散負荷テスト環境構築
  2. CI/CD統合
  3. 自動パフォーマンス監視

🎉 結論

API Gateway + Lambda構成は優秀な結果を示しました

100%成功率 - 完全な可用性を実現
25.96ms平均応答 - 非常に高速なレスポンス
51.6 RPS - 高いスループットを達成
サーバーレス - 管理不要で運用コスト削減

この結果は、サーバーレスアーキテクチャでも高いパフォーマンスと信頼性を実現できることを証明しています。

📋 アクションアイテム

優先度 アクション 担当 期限
Lambda メモリ増加 DevOps 1週間
高負荷テスト実施 QA 2週間
Provisioned Concurrency検討 Architecture 1ヶ月
監視ダッシュボード作成 DevOps 2ヶ月

と、Amazon Qは分析してくれました!

こんな時は...トラブルシューティング

タスクが起動しない

  • CloudWatch Logsでエラーを確認
  • セキュリティグループの設定を確認
  • ECRイメージのプルに失敗していないか確認

APIにリクエストが届かない

  • ネットワーク設定(VPC、サブネット)を確認
  • NATゲートウェイの設定を確認(プライベートサブネットの場合)
  • APIのセキュリティグループでECSからのアクセスを許可

応答時間が遅い

  • ECSタスクのCPU/メモリを増やす
  • Workerを追加してリクエストを分散
  • APIサーバー側のスケーリング設定を確認

まとめ

ECS Fargateで負荷テストツールLocustを動かして、APIに負荷をかける方法をやってみました。

おさらい

✅ LocustはPythonで簡単に負荷テストシナリオを書ける
✅ ECS Fargateでサーバー管理不要で実行できる
✅ WebUIで結果をリアルタイムに確認できる

次のステップ

  • Locustの分散実行機能(Master-Worker構成)で負荷試験してみる
  • より複雑なシナリオを作成してみる
  • CloudWatch Metricsと連携して監視を強化
  • カスタムレポートの作成

負荷テストは、システムの性能を把握し、ボトルネックを発見するために重要です。ぜひ、この記事を参考に実際に試してみてください!
次回のブログでは、Master-Worker構成の検証をしてみたいと思います。

参考リンク

投稿者プロフィール

YoshiSaaaan
2023/1にスカイアーチネットワークスにJoin
AWSを日々勉強中