負荷テストを実施するにあたって、負荷テストを実行するためのdockerコンテナを作ることにした。
dockerコンテナを作った理由はとしては下記のとおり。
- どの環境でもコンテナを展開すればすぐに使える
- 状況に応じてdockerコンテナ間の通信上での負荷テストと、インターネット経由での負荷テストが切り替えやすい
- テストケースを入れ替えるだけで他のプロジェクトでも使える
特に今回はテスト対象となるシステムがAWS上で動いており、インターネット経由で負荷テストを実施するとCloudFront、WAF、ALBなどに大量のデータが行き交うことでコストが増大する可能性があったため、それらを経由せずにdockerコンテナ間で通信ができることが必要だった
(コスト計算した結果、100数円で済むことがわかったので最終的にはインターネット経由で実施した)
docker file
# イメージ
FROM openjdk:8-slim
# JMeterのバージョン指定
ARG JMETER_VERSION=5.6.3
# JMeterのダウンロードと解凍、不要ファイルの削除を一つのRUNコマンドで実行
# 事前のデータ投入をpythonスクリプトで実施するのでpythonもインストールしている
RUN apt-get update \
&& apt-get install -y wget tzdata python3-pip \
&& ln -fs /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \
&& dpkg-reconfigure -f noninteractive tzdata \
&& wget https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-${JMETER_VERSION}.tgz \
&& tar -xzf apache-jmeter-${JMETER_VERSION}.tgz \
&& rm apache-jmeter-${JMETER_VERSION}.tgz \
&& mv apache-jmeter-${JMETER_VERSION} /jmeter \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# PythonからMySQLへデータ投入するために必要なパッケージ
RUN pip3 install pymysql
# 環境変数の設定
ENV JMETER_HOME=/jmeter
ENV PATH=$JMETER_HOME/bin:$PATH
# 各種ファイルをコンテナにコピー
COPY *.jmx /.
# データ投入用のスクリプトをコピー
COPY data_insert.py /data_insert.py
COPY data_delete.py /data_delete.py
# データ登録→テスト実行→データ削除の順に実行
CMD /bin/sh -c 'python3 /data_insert.py && \
TIMESTAMP=$(date +%Y%m%d-%H%M%S) && \
jmeter -n -t /$JMX -l /report/results-$TIMESTAMP.jtl -e -o /report/report-$TIMESTAMP && \
python3 /data_delete.py'
解説
FROM openjdk:8-slim
JMeterを動作させるにはJava8以上が必要だったので、OpenJDK 8の軽量なDockerイメージを指定しています。
RUN apt-get update \
&& apt-get install -y wget tzdata python3-pip \
&& ln -fs /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \
&& dpkg-reconfigure -f noninteractive tzdata \
&& wget https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-${JMETER_VERSION}.tgz \
&& tar -xzf apache-jmeter-${JMETER_VERSION}.tgz \
&& rm apache-jmeter-${JMETER_VERSION}.tgz \
&& mv apache-jmeter-${JMETER_VERSION} /jmeter \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUNコマンドでは、JMeterをDLするためのwget、タイムゾーンをしているためのtzdata、事前データの投入と削除を行うスクリプトを実行するためのpython3をインストールしています。
その後、タイムゾーンの指定、JMeterのインストールをした後、不要なファイルの削除をしています。
CMD /bin/sh -c 'python3 /data_insert.py && \
TIMESTAMP=$(date +%Y%m%d-%H%M%S) && \
jmeter -n -t /$JMX -l /report/results-$TIMESTAMP.jtl -e -o /report/report-$TIMESTAMP && \
python3 /data_delete.py'
最後に、CMDで、データの登録、テストの実行、データの削除を順に実行するシェルスクリプトを指定しています。
テスト結果はタイムスタンプ付きのファイルに保存され、後で分析できるようにしています。
その他
実行する時に通信先やデータ量、レポート出力先を変更できるようにDocker実行時に環境変数ファイルを指定している
docker run --env-file docker/stresstest/local.env -v $(pwd)/report:/report my-stress-test
環境変数ファイルで定義した内容をJMeterに渡す場合は下記のように-Jをつけて実行する。
CMD /bin/sh -c `jmeter -JAPI_BASE_URL="$API_BASE_URL" -n -t /$JMX -l /report/results-$TIMESTAMP.jtl -e -o /report/report-$TIMESTAMP`
上記の場合、環境変数ファイル内のAPI_BASE_URLがAPI_BASE_URLという名前でJMeterに渡される。
これをJMeterで扱うにはユーザー定義変数で${__P(API_BASE_URL)}とすれば取得できる