1. 序章

このチュートリアルでは、Gatlingを使用して分散パフォーマンステストを実行する方法を理解します。 その過程で、Gatlingでテストするための簡単なアプリケーションを作成し、分散パフォーマンステストを使用する理由を理解し、最後に、それを達成するためにGatlingで利用できるサポートを理解します。

2. ガトリングによるパフォーマンステスト

パフォーマンステストは、特定のワークロードでのシステムの応答性と安定性を評価するテスト手法です。 一般的にパフォーマンステストの対象となるテストにはいくつかの種類があります。 これらには、負荷テスト、ストレステスト、ソークテスト、スパイクテスト、およびその他のいくつかが含まれます。 これらはすべて、達成すべき独自の特定の目的を持っています。

ただし、パフォーマンステストの一般的な側面の1つはワークロードをシミュレートすることであり、 Gatling JMeter K6などのツールがそれを支援します。 ただし、先に進む前に、パフォーマンスをテストできるアプリケーションが必要です。

次に、このアプリケーションのパフォーマンステスト用の単純なワークロードモデルを開発します。

2.1. アプリケーションの作成

このチュートリアルでは、SpringCLIを使用して簡単なSpring BootWebアプリケーションを作成します。

spring init --dependencies=web my-application

次に、リクエストに応じて乱数を提供する単純なRESTAPIを作成します。

@RestController
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @GetMapping("/api/random")
    public Integer getRandom() {
        Random random = new Random();
        return random.nextInt(1000);
    }
}

このAPIには特別なことは何もありません。呼び出しごとに、0から999の範囲のランダムな整数を返すだけです。

このアプリケーションの起動は、Mavenコマンドを使用すると非常に簡単です。

mvnw spring-boot:run

2.2. ワークロードモデルの作成

この単純なAPIを本番環境にデプロイする必要がある場合は、予想される負荷を処理し、必要なサービス品質を提供できることを確認する必要があります。 ここで、さまざまなパフォーマンステストを実行する必要があります。 ワークロードモデルは通常、実際の使用法をシミュレートするために1つ以上のワークロードプロファイルを識別します

ユーザーインターフェイスを備えたWebアプリケーションの場合、適切なワークロードモデルを定義することは非常に難しい場合があります。 ただし、単純なAPIの場合、負荷テストの負荷分散について仮定を立てることができます。

Gatlingは、シミュレーションでテストするシナリオを作成するためのScalaDSLを提供します。 前に作成したAPIの基本的なシナリオを作成することから始めましょう。

package randomapi

import io.gatling.core.Predef._
import io.gatling.core.structure.ScenarioBuilder
import io.gatling.http.Predef._
import io.gatling.http.protocol.HttpProtocolBuilder

class RandomAPILoadTest extends Simulation {
    val protocol: HttpProtocolBuilder = http.baseUrl("http://localhost:8080/")
    val scn: ScenarioBuilder = scenario("Load testing of Random Number API")
      .exec(
        http("Get Random Number")
          .get("api/random")
          .check(status.is(200))
      )

    val duringSeconds: Integer = Integer.getInteger("duringSeconds", 10)
    val constantUsers: Integer = Integer.getInteger("constantUsers", 10)
    setUp(scn.inject(constantConcurrentUsers(constantUsers) during (duringSeconds))
      .protocols(protocol))
      .maxDuration(1800)
      .assertions(global.responseTime.max.lt(20000), global.successfulRequests.percent.gt(95))
}

この基本的なシミュレーションの重要なポイントについて説明しましょう。

  • まず、必要なGatlingDSLインポートをいくつか追加します。
  • 次に、HTTPプロトコル構成を定義します
  • 次に、APIへの単一のリクエストでシナリオを定義します
  • 最後に、注入する負荷のシミュレーション定義を作成します。 ここでは、10人の同時ユーザーを10秒間使用して負荷を注入しています

ユーザーインターフェイスを備えたより複雑なアプリケーション用にこの種のシナリオを作成することは、非常に複雑になる可能性があります。 ありがたいことに、Gatlingには、レコーダーと呼ばれる別のユーティリティが付属しています。 このレコーダーを使用して、ブラウザーとサーバー間の相互作用をプロキシさせることでシナリオを作成できます。 また、 HAR(HTTPアーカイブ)ファイルを使用してシナリオを作成することもできます。

2.3. シミュレーションの実行

これで、負荷テストを実行する準備が整いました。 このために、シミュレーションファイル「RandomAPILoadTest.scala」をディレクトリ「%G ATLING_HOME % / user-file /randomapi/」に配置できます。これが唯一の方法ではないことに注意してください。シミュレーションを実行しますが、それは確かに最も簡単なものの1つです。

次のコマンドを実行して、ガトリングを開始できます。

$GATLING_HOME/bin/gatling.sh

これにより、実行するシミュレーションを選択するように求められます。

Choose a simulation number:
     [0] randomapi.RandomAPILoadTest

シミュレーションを選択すると、シミュレーションが実行され、要約を含む出力が生成されます。

さらに、ディレクトリ「%G ATLING_HOME %/results」にHTML形式のレポートを生成します。

これは、生成されるレポートのの一部にすぎませんが、結果の要約をはっきりと見ることができます。 これは非常に詳細で、簡単に理解できます。

3. 分散パフォーマンステスト

ここまでは順調ですね。 しかし、思い出すと、パフォーマンステストの目的は、実際のワークロードをシミュレートすることです。 このは、一般的なアプリケーションでは、ここでの些細なケースで見た負荷よりも大幅に高くなる可能性があります。 テストの概要でわかるように、約500リクエスト/秒のスループットを達成することができました。 実際のワークロードを処理する実際のアプリケーションの場合、これは何倍も高くなる可能性があります。

パフォーマンスツールを使用して、この種のワークロードをどのようにシミュレートしますか? 単一のマシンから負荷を注入するだけでこれらの数値を達成することは本当に可能ですか? おそらくそうではありません。 ロードインジェクションツールがはるかに高い負荷を処理できる場合でも、基盤となるオペレーティングシステムとネットワークには独自の制限があります

ここで、負荷注入を複数のマシンに分散させる必要があります。 もちろん、他の分散コンピューティングモデルと同様に、これには独自の課題が伴います。

  • 参加しているマシン間でワークロードをどのように分散しますか?
  • 発生する可能性のあるエラーからの完了と回復を調整するのは誰ですか?
  • 統合レポートの結果をどのように収集して要約しますか?

分散パフォーマンステストの一般的なアーキテクチャでは、マスターノードとスレーブノードを使用して、次の懸念事項のいくつかに対処します。

しかし、ここでも、マスターが故障した場合はどうなりますか? 分散コンピューティングのすべての懸念に対処することはこのチュートリアルの範囲ではありませんが、パフォーマンステスト用の分散モデルを選択する際には、それらの影響を確実に強調する必要があります。

4. ガトリングを使用した分散パフォーマンステスト

分散パフォーマンステストの必要性を理解したので、Gatlingを使用してこれをどのように達成できるかを見ていきます。 クラスタリングモードは、GatlingFrontlineの組み込み機能です。 ただし、FrontlineはGatlingのエンタープライズバージョンであり、オープンソースとしては利用できません。 Frontlineは、オンプレミスまたは一般的なクラウドベンダーのいずれかにインジェクターをデプロイすることをサポートしています。

それでも、Gatlingオープンソースでこれを実現することは可能です。 しかし、私たちは自分たちで大部分の重労働をしなければなりません。 このセクションでは、それを実現するための基本的な手順について説明します。 ここでは、前に定義したのと同じシミュレーションを使用して、複数のマシンの負荷を生成します。

4.1. 設定

まず、オンプレミスまたはクラウドベンダーのいずれかで、コントローラーマシンといくつかのリモートワーカーマシンを作成します。 これらすべてのマシンで実行する必要がある特定の前提条件があります。 これには、すべてのワーカーマシンへのGatlingオープンソースのインストール、およびいくつかのコントローラーマシン環境変数の設定が含まれます。

一貫した結果を得るには、すべてのワーカーマシンに同じバージョンのガトリングをインストールし、それぞれに同じ構成を設定する必要があります。 これには、Gatlingをインストールするディレクトリと、それをインストールするために作成するユーザーが含まれます。

コントローラマシンに設定する必要のある重要な環境変数を見てみましょう。

HOSTS=( 192.168.x.x 192.168.x.x 192.168.x.x)

また、負荷を注入するために使用するリモートワーカーマシンのリストも定義しましょう。

GATLING_HOME=/gatling/gatling-charts-highcharts-1.5.6
GATLING_SIMULATIONS_DIR=$GATLING_HOME/user-files/simulations
SIMULATION_NAME='randomapi.RandomAPILoadTest'
GATLING_RUNNER=$GATLING_HOME/bin/gatling.sh
GATLING_REPORT_DIR=$GATLING_HOME/results/
GATHER_REPORTS_DIR=/gatling/reports/

一部の変数は、シミュレーションを開始するために必要なGatlingインストールディレクトリおよびその他のスクリプトを指します。 また、レポートを生成するディレクトリについても説明します。 それらをどこで使用するかは後で説明します。

マシンがLinuxのような環境を備えていることを前提としていることに注意することが重要です。 ただし、Windowsなどの他のプラットフォームに手順を簡単に適合させることができます。

4.2. 負荷の分散

ここでは、同じシナリオを以前に作成した複数のワーカーマシンにコピーします。 シミュレーションをリモートホストにコピーするには、いくつかの方法があります。 最も簡単な方法は、サポートされているホストにscpを使用することです。 シェルスクリプトを使用してこれを自動化することもできます。

for HOST in "${HOSTS[@]}"
do
  scp -r $GATLING_SIMULATIONS_DIR/* $USER_NAME@$HOST:$GATLING_SIMULATIONS_DIR
done

上記のコマンドは、ローカルホスト上のディレクトリの内容をリモートホスト上のディレクトリにコピーします。 Windowsユーザーの場合、 PuTTY は、PSCP(PuTTYセキュアコピープロトコル)にも付属している優れたオプションです。 PSCPを使用して、WindowsクライアントとWindowsまたはUnixサーバー間でファイルを転送できます。

4.3. シミュレーションの実行

シミュレーションをワーカーマシンにコピーしたら、それらをトリガーする準備が整います。 同時ユーザーの総数を達成するための鍵は、すべてのホストでほぼ同時にシミュレーションを実行することです。

シェルスクリプトを使用して、このステップを再び自動化できます。

for HOST in "${HOSTS[@]}"
do
  ssh -n -f $USER_NAME@$HOST \
    "sh -c 'nohup $GATLING_RUNNER -nr -s $SIMULATION_NAME \
    > /gatling/run.log 2>&1 &'"
done

ssh を使用して、リモートワーカーマシンでシミュレーションをトリガーしています。 ここで注意すべき重要な点は、「レポートなし」オプション(-nr)を使用していることです。 これは、この段階ではログの収集にのみ関心があり、後ですべてのワーカーマシンからのログを組み合わせてレポートを作成するためです。

4.4. 結果の収集

次に、すべてのワーカーマシンでシミュレーションによって生成されたログファイルを収集する必要があります。 これも、シェルスクリプトを使用して自動化し、コントローラーマシンから実行できるものです。

for HOST in "${HOSTS[@]}"
do
  ssh -n -f $USER_NAME@$HOST \
    "sh -c 'ls -t $GATLING_REPORT_DIR | head -n 1 | xargs -I {} \
    mv ${GATLING_REPORT_DIR}{} ${GATLING_REPORT_DIR}report'"
  scp $USER_NAME@$HOST:${GATLING_REPORT_DIR}report/simulation.log \
    ${GATHER_REPORTS_DIR}simulation-$HOST.log
done

シェルスクリプトに精通していない私たちにとって、コマンドは複雑に見えるかもしれません。 しかし、それらを分割するときはそれほど複雑ではありません。 まず、 ssh をリモートホストに挿入し、Gatlingレポートディレクトリ内のすべてのファイルを時系列の逆順に一覧表示して、最初のファイルを取得します。

次に、選択したログファイルをリモートホストからコントローラーマシンにコピーし、名前を変更してホスト名を追加します。 異なるホストからの同じ名前の複数のログファイルがあるため、これは重要です。

4.5. レポートの生成

最後に、さまざまなワーカーマシンで実行されたシミュレーションから収集されたすべてのログファイルからレポートを生成する必要があります。 ありがたいことに、Gatlingはここですべての面倒な作業を行います。

mv $GATHER_REPORTS_DIR $GATLING_REPORT_DIR
$GATLING_RUNNER -ro reports

すべてのログファイルを標準のGatlingレポートディレクトリにコピーし、Gatingコマンドを実行してレポートを生成します。 これは、コントローラーマシンにもGatlingがインストールされていることを前提としています。 最終的なレポートは、以前に見たものと似ています。

ここでは、実際に複数のマシンから負荷が注入されていることに気づいていません。 3台のワーカーマシンを使用した場合、リクエスト数はほぼ3倍になっていることがはっきりとわかります。 ただし、実際のシナリオでは、スケーリングはこれほど完全に線形ではありません。

5. スケーリングパフォーマンステストに関する考慮事項

分散パフォーマンステストは、パフォーマンステストをスケーリングして実際のワークロードをシミュレートする方法であることがわかりました。 現在、分散パフォーマンステストは便利ですが、微妙な違いがあります。 したがって、負荷注入機能を可能な限り垂直方向にスケーリングするように確実に試みる必要があります。 単一のマシンで垂直方向の制限に達した場合にのみ、分散テストの使用を検討する必要があります。

通常、マシンの負荷注入をスケーリングするための制限要因は、基盤となるオペレーティングシステムまたはネットワークに由来します。 これを改善するために最適化できることがいくつかあります。 Linuxのような環境では、ロードインジェクターが生成できる同時ユーザーの数は、通常、開いているファイルの制限によって制限されます。 ulimitコマンドを使用して増やすことを検討できます。

もう1つの重要な要素は、マシンで利用可能なリソースに関するものです。 たとえば、ロードインジェクションは通常、多くのネットワーク帯域幅を消費します。 マシンのネットワークスループットが制限要因である場合は、アップグレードを検討できます。 同様に、マシンで使用可能なCPUまたはメモリが他の制限要因になる可能性があります。 クラウドベースの環境では、より強力なマシンに切り替えるのはかなり簡単です。

最後に、シミュレーションに含めるシナリオは、常に負荷がかかっている状態で肯定的な応答を想定するべきではないため、回復力がある必要があります。 したがって、応答に関するアサーションを作成する際には、注意深く防御する必要があります。 また、スループットを向上させるための労力を節約するために、アサーションの数を最小限に抑える必要があります

6. 結論

このチュートリアルでは、Gatlingを使用して分散パフォーマンステストを実行するための基本を説明しました。 テスト用の簡単なアプリケーションを作成し、Gatlingで簡単なシミュレーションを開発してから、複数のマシンからこれを実行する方法を理解しました。

その過程で、分散パフォーマンステストの必要性とそれに関連するベストプラクティスも理解しました。