負荷テストとは?

新しいアプリケーションや機能は、ほとんどの場合、ユーザーによるアクセスや利用が始まったばかりのときにはとても順調に動作しているものです。 しかし、ユーザー ベースが拡大し使用量が増えると、当初のインフラストラクチャではアプリを支えられなくなり、 ユーザーがパフォーマンスの低下を感じるようになります。 待ち時間が増え、帯域幅やメモリはあっという間に使い尽くされ、コード アーキテクチャの一部でエラーが発生するようになってしまいます。原因は、ユーザー数の増加に合わせてインフラストラクチャが適切にスケーリングされていないことにあります。 これは予想外の事態ではありません。インフラストラクチャとアプリケーション アーキテクチャは、使用量の増加に合わせてスケーリングする必要があるものだからです。 問題は、サーバーへの負荷の増加が原因でアプリケーションがいつ “壊れて” しまうのか、インフラストラクチャがいつダウンするのかが、事前にわからないことです。 特に金銭面で、大きな損失につながりかねません。

そのため、ソフトウェア アプリケーション ライフサイクルでは、負荷テストが最も重要なテストの 1 つとされています。 負荷テストでは、本番環境で想定される負荷をアプリケーションにかけます。 このテストで得た情報に基づいて、アプリケーションのパフォーマンスがしきい値を下回ることがないように、インフラストラクチャとアプリケーションを調整できます。

本チュートリアルでは、Apache Benchmark という HTTP サーバー用の負荷テストとベンチマーク ツールを使用して、シンプルな Node.js API に対して負荷テストを行います。

前提条件

このチュートリアルを進めるには、いくつかの準備が必要です。

  1. JavaScript の基礎を理解する
  2. Node.js (バージョン 10.3 以上) をローカル システムにインストールする
  3. Heroku アカウントを用意する
  4. CircleCI アカウントを用意する
  5. GitHub アカウントを用意する

これらのインストールとセットアップが済んだら、チュートリアルを始めましょう。

ホスティング用の Heroku アプリをセットアップする

まず、API をホストするための Heroku アプリケーションをセットアップします。 Heroku アプリ ダッシュボードに移動して、 [New (新規)]、[Create new app (新規アプリを作成)] の順にクリックします。 任意の名前を使用して、新規アプリを作成します。

新規アプリ - Heroku

指定したアプリ名 (上図では node-loadtest) をメモします。 この情報は、このチュートリアルで後ほど必要になります。

次に、ダッシュボードの [Account Settings (アカウント設定)] セクションで Heroku API キーを確認します。

Heroku トークン

この情報もチュートリアルで後ほど必要になります。

テスト プロジェクトをクローンする

次に、チュートリアル用の API プロジェクトをクローンします。 この API プロジェクトはシンプルな Node.js API アプリケーションであり、ルート エンドポイント 1 つと、ユーザーのコレクションをフェッチするためのエンドポイント 1 つで構成されています。 以下のコマンドを実行して、プロジェクトをクローンします。

git clone --single-branch --branch base-project https://github.com/coderonfleek/node-loadtest

クローンが完了したら、以下のコマンドを実行して、プロジェクトのルートに移動し依存関係をインストールします。

cd node-loadtest
npm install

インストールが完了したら、以下のコマンドでアプリケーションを実行します。

npm start

アプリケーションがデフォルト ポート 3000 でのリッスンを開始します。 Postman を開き、http://localhost:3000/users/get エンドポイントに対して GET リクエストを行ってみましょう。 ユーザーの配列が返されれば成功です。

ユーザーの取得 - Postman

上図のような結果が得られれば、 API は正常に機能しています。

CircleCI に接続する

CircleCI で API プロジェクトをセットアップするために、まず、プロジェクトを GitHub にプッシュする必要があります。

次に、CircleCI ダッシュボードの [Projects (プロジェクト)] ページに移動し、(適切な GitHub アカウントを選択して) プロジェクトを追加します。

プロジェクトの追加 - CircleCI

[Set Up Project (プロジェクトをセットアップ)] ボタンをクリックして、設定を始めましょう。 下図の画面が開きます。

設定ファイルの追加 - CircleCI

セットアップ ページで、表示されたサンプルを無視して設定ファイルを手動で追加するため、[Use Existing Config (既存の設定ファイルを使用する)] をクリックします。 パイプラインの設定ファイルをダウンロードするのか、ビルドを開始するのかを確認するメッセージが表示されます。

ビルドに関するプロンプト - CircleCI

[Start Building (ビルドの開始)] をクリックします。 設定ファイルのセットアップがまだのため、このビルドは失敗します。 このセットアップ作業は後ほど行います。

最後に、先ほど追加したプロジェクトの環境変数を設定します。 これにより、デプロイ用 Heroku アプリケーションへの認証済みアクセスが可能になります。

パイプライン ページで [Project Settings (プロジェクト設定)] ボタンをクリックして、プロジェクト設定に移動します。 このチュートリアルのプロジェクトが選択されていることを確認してください。

プロジェクト設定 - CircleCI

プロジェクト設定ページのサイド メニューにある [Environment Variables (環境変数)] をクリックします。

環境変数のページで、[Add Environment Variable (環境変数を追加)] をクリックします。

環境変数の追加 - CircleCI

以下の環境変数を追加します。

  • HEROKU_APP_NAME: Heroku アプリケーションの名前 (今回は cci-node-loadtest)
  • HEROKU_API_KEY: Heroku アカウントの API キー (前述)

環境変数 - CircleCI

これで、Heroku にデプロイするための CircleCI コンソールでのセットアップはすべて完了です。

パイプライン設定ファイルに負荷テストを追加する

いよいよ、デプロイ パイプラインをビルドします。パイプラインでは、デプロイのたびに、API の /users/get エンドポイントの負荷テストを行います。 プロジェクトのルートに、.circleci という名前のフォルダーを作成して、config.yml という名前のファイルをその中に作成します。 config.yml に、以下のコードを入力します。

jobs:
  build:
    executor: heroku/default
    steps:
      - checkout
      - heroku/install
      - heroku/deploy-via-git

  loadtestapi:
    docker:
      - image: circleci/node:10.16.3
    steps:
      - run:
          name: 負荷テストの実行
          command: |
            sudo apt-get update
            sudo apt-get install apache2-utils
            ab -k -c 20 -n 250 https://$HEROKU_APP_NAME.herokuapp.com/users/get

orbs:
  heroku: circleci/heroku@0.0.10
version: 2.1
workflows:
  deploy:
    jobs:
      - build
      - loadtestapi:
          requires:
            - build

ここで作成した設定ファイルには、次の 2 つのジョブが含まれています。

  • build ジョブ: CircleCI の Heroku Orb を使用して、API プロジェクトを GitHub リポジトリからホスティング プラットフォーム上の Heroku アプリにデプロイします。

  • loadtestapi ジョブ: API のデプロイ後、Apache Benchmark ツールをインストールし、ツールから 250 件のリクエストを /users/get エンドポイントに送信します。その際の同時実行数は 20 で、持続的な接続を行うために -k フラグで Keep-Alive 接続を指定しています。

API が正常にデプロイされるまで負荷テストが実行されないように、ワークフローを使用して、loadtestapi ジョブの実行を build ジョブの完了まで待機させています。

それでは、負荷テスト パイプラインを実行しましょう。 すべての変更をプロジェクトにコミットして、リモート GitHub リポジトリにプッシュします。 これで自動的にパイプラインがトリガーされ、ビルドが成功します。

ビルド成功 - CircleCI

ワークフローで loadtestapi ジョブをクリックして、負荷テストの結果を確認します。

ビルドの詳細 - CircleCI

結果から、250 個のリクエストすべてが 0.44 秒以内に処理されたことがわかります。 これが望ましい結果かどうかは、みなさんそれぞれがアプリケーションに設定したパフォーマンス メトリクスによって異なります。 CircleCI では、他にもテスト実行に関するさまざまな詳細情報を確認できます。 これらの情報は、アプリケーション ユーザーの増加に合わせて、アプリケーション アーキテクチャを調整しスケーリングする際に役立ちます。

おわりに

大企業でもスタートアップ企業でも、ソフトウェアをユーザーに提供するのであれば、負荷テストはきわめて重要です。 負荷テストを行うことで、ユーザーの利用中にダウンタイムが発生する事態を回避できます。 このチュートリアルでは、API のデプロイ直後に、Web トラフィックの処理能力を確かめる負荷テストを実行する方法を学びました。 Apache Benchmark によるこのような負荷テストは、さまざまな方法で拡張できます。 他にも、負荷テスト プロセスに組み込める専用ツールや、Apache Benchmark の代わりに利用できる k6 などのツールも存在します。

Happy coding!


Fikayo Adepoju は、Web とモバイル テクノロジー、DevOps に精通したフルスタック開発者、テクニカル ライター、テクニカル コンテンツ クリエイターです。スケーラブルな分散アプリケーション開発については 10 年以上の経験を持っています。 CircleCI、Twilio、Auth0、The New Stack のブログで 40 以上の記事を執筆するほか、個人の Medium ページでも情報を発信しており、役立つ知識を多くの開発者に広めることに専心しています。 また、Udemy で動画形式のコース (英語) も開講しています。ぜひご覧ください。