Gatling のスケールアウト構成

Page content

gatling で負荷をかけるにも、サーバ1台では限界がある。複数台での負荷試験を実現すべく、 master と slave 群を作りたい。そうすれば スケールアウト用スクリプト が動く。

実装パターン

  • A. Amazon EC2 で地道にやる

    • 作ってイメージをコピーしまくって、IPアドレスと ssy key をちゃんと埋め込めばそりゃあ gatling 公式通りに動くよね。
    • インスタンスを AMI イメージ化してしまうのでも良さそう
  • B. docker + nginx のコンテナを作って Amazon ECS にデプロイしまくる

    • インスタンスの構築は楽
    • master もこれで作る?
    • ファイルのやり取りや指示は ssh 経由なのか、 docker exec -it 経由なのか?リモートに docker exec -it できる?

A. Amazon EC2 で構成する方法

これは出来たよ出来た。

EC2 インスタンス群の作成

  • OS: AMI (Amazon Linux AMI 2018.03.0 (HVM), SSD Volume Type - ami-00a5245b4816c38e6)
  • インスタンスタイプ: 例えば c4.large (TシリーズはCPUクレジットがあっという間になくなって動かなくなるため注意)
  • ユーザーデータ(起動直後に実行させるスクリプト): ここで動作要件である java 1.8を入れて、 gatling をダウンロード
    #!/bin/bash -x
    yum remove -y java-1.7.0-openjdk-1.7.0.201-2.6.16.0.78.amzn1.x86_64
    yum update -y
    yum -y install java-1.8.0-openjdk java-1.8.0-openjdk-devel
    yum clean all
    wget https://repo1.maven.org/maven2/io/gatling/highcharts/gatling-charts-highcharts-bundle/2.3.1/gatling-charts-highcharts-bundle-2.3.1-bundle.zip && \
    unzip gatling-charts-highcharts-bundle-2.3.1-bundle.zip && \
    mv -f gatling-charts-highcharts-bundle-2.3.1 gatling
    mv gatling /home/ec2-user/.
    chown -R ec2-user:ec2-user /home/ec2-user/gatling
    
  • うまく行っていなかったら /var/log/cloud-init-output.log を見よう。
  • ディスク: 16GBもあれば十分かな
  • IPを調べる: もし auto-scaling group に入れるならそれを条件にフィルタしてIPを一括取得
    aws ec2 describe-instances --profile t12-george --filters "Name=tag:aws:autoscaling:groupName,Values=gatling-autoscaling-group2" | jq '.Reservations[].Instances[].PublicIpAddress'
    
  • ただし auto-scaling group は扱いづらいかも。

作ったインスタンス群から選んだ master に設定

  • ディレクトリツリー : EC2上では /home/ec2-user/gatling/ の部分

    gatling
    ├── bin
    │   ├── gatling.sh  # built-in execution script
    │   └── scaleout.sh  # put your customized scaleout test script
    ├── conf
    │   ├── logback.xml  # debug log setting
    │   └── gatling.conf  # performance tuning
    ├── lib
    │   └── zinc
    ├── results
    │   └── my-scenario1-1528429451035  # generated result html items
    │       ├── index.html
    │       ├── js
    │       └── style
    ├── target
    │   └── test-classes
    │       └── computerdatabase
    │           └── advanced
    └── user-files
        ├── bodies
        ├── data
        │   └── mydata.csv  # input parameters
        ├── log
        └── simulations
            ├── myproject  # your test scenario by scala here
            └── computerdatabase
    
  • logback.xml (optional): 必要に応じてエラーだけ詳細出力するよう設定:

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
    
        <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <pattern>%d{HH:mm:ss.SSS} [%-5level] %logger{15} - %msg%n%rEx</pattern>
            </encoder>
        <immediateFlush>false</immediateFlush>
        </appender>
    
        <!-- Uncomment for logging ALL HTTP request and responses -->
        <!-- 	<logger name="io.gatling.http.ahc" level="TRACE" /> -->
        <!--    <logger name="io.gatling.http.response" level="TRACE" /> -->
        <!-- Uncomment for logging ONLY FAILED HTTP request and responses -->  やるならここを uncomment!
        <!-- 	<logger name="io.gatling.http.ahc" level="DEBUG" /> -->
        <!--    <logger name="io.gatling.http.response" level="DEBUG" /> -->
    
        <root level="WARN">
            <appender-ref ref="CONSOLE" />
        </root>
    
    </configuration>
    
  • bin/scaleout.sh : 公式のスクリプト を参考にIP変えたり頑張れ!

  • ssh private key の設置と権限設定 (masterに設定し、slaveたちにアクセスできるように)

    scp -i <key> <key> ec2-user@master:~/.ssh/.
    ssh -i <key> ec2-user@master -t chmod 400 <key>'
    
  • その他チューニング

    • ソケット枯渇・ファイルディスクリプタ枯渇対策のチューニング: https://qiita.com/shokos@github/items/78d994d6673d8eb44348
    • gatling.conf : timeout 時間チューニング
      • gatling > http > ahc > requestTimeout あたりが GET リクエストの待ち時間かなぁ(結局まだ触ったこと無い)

実行方法

  • 詳細リファレンス: command line option

  • -s で自分のシナリオを指定できます

    $ cd gatling
    $ ./bin/gatling.sh -s computerdatabase.MySimulation
    
  • クラス名はシナリオファイルの先頭の方を見ればわかる。以下の例なら computerdatabase.my_test_24h:

    package computerdatabase
    
    import io.gatling.core.Predef._
    import io.gatling.http.Predef._
    import scala.concurrent.duration._
    
    class my_test_24h extends Simulation {
        ...
    }
    
  • 実行方法

    cd ~/gatling/
    bash bin/scaleout.sh
    
  • 実行後にレポートを手元にscp でもして確認しよう。それか master に apache でも起動させてもよい(長時間負荷をかけるとログが重たくなるのでそのほうがbetterかも)

B. docker + nginx のコンテナを作って ECS にデプロイ (未完成)

docker-composer で nginx + gatling を構築:

  • ref: GatlingとnginxのDockerコンテナを構築する
  • gatling 用 Dockerfile を最新化:
    FROM cemmersb/centos-jdk8
    ENV LANG C.UTF-8
    
    # install necessary packages
    RUN yum install -y zip unzip
    
    # Donwload and Unzip Gatling
    RUN cd /usr/local/bin/ && \
      wget https://repo1.maven.org/maven2/io/gatling/highcharts/gatling-charts-highcharts-bundle/2.3.1/gatling-charts-highcharts-bundle-2.3.1-bundle.zip && \
      unzip gatling-charts-highcharts-bundle-2.3.1-bundle.zip && \
      mv -f gatling-charts-highcharts-bundle-2.3.1 gatling
    

docker イメージを ECS に up する

ref: 公式

  1. レジストリに対して Docker クライアントを認証するために使用するログインコマンドを取得します。 macOS または Linux システムの場合は、AWS CLI を使用します:
$(aws ecr get-login --no-include-email --region ap-northeast-2 --profile xxxxxxxx)
  1. 上記の出力結果をシェルに貼り付けて実行
  2. 以下のコマンドを使用して、Docker イメージを構築します。Docker ファイルを一から作成する場合は、こちらの手順を参照してください。イメージがすでに構築されている場合は、この手順を省略できます:
docker build -t gatling/gatling .
  1. 構築が完了したら、このリポジトリにイメージをプッシュできるように、イメージにタグを付けます:
docker tag gatling/gatling:latest <id>.dkr.ecr.ap-northeast-2.amazonaws.com/gatling/gatling:latest
  1. 以下のコマンドを実行して、新しく作成した AWS リポジトリにこのイメージをプッシュします:
docker push <id>.dkr.ecr.ap-northeast-2.amazonaws.com/gatling/gatling:latest

docker-composer で ECS にデプロイ

ref: ECS CLIを使ってDocker Composeのファイルを使ってECSにデプロイする

  • ECS-CLIを使う事をで簡単にDockerComposeで作った環境をAWSにデプロイできる
  • コマンドはdocker-composeに似ているので覚えやすい
  • ECS-CLIでbuildディレクティブは現在使えないので、利用するイメージは予めビルドしておくこと
  • ECS-CLIがGoで書かれており、バイナリなのでインストールが楽
  • ECSでt2.microなど少ないスペックで実施する場合、複数コンテナ起動時にメモリ不足で起動できない場合があるので、その場合、mem_limitディレクティブなどで調整が必要