こんにちは、Mikuです。
dockerであれこれ環境構築を自動化したり、Jenkinsで手作業やビルド・デプロイを自動化したり、サーバを構築したり、たまに開発をしたり、いろいろなことに取り組んでいるエンジニアです。
この記事は下記にあてはまる方にぜひ読んでほしいです。
(特にプロキシ環境下の方は作業の参考としたい記事にプロキシについての記載がされていないことも多く、時間をかけてしまった経験もあるかと思います)
本記事のテーマは Apacheが公開しているWebアプリの負荷テストツールのJMeterをServer - Client構成で実行したい、というものです。
Server、Client はそれぞれdockerコンテナとして作成し、Clientとなるコンテナからよりスペックの高いサーバにあるServer役コンテナに命令を送りJMeterを実行させます。
また別記事で取り上げますが、実行中のJMeterメトリクスをInfluxDBに送り、その結果をGrafanaで可視化させることも目標とします。
Apache JMeter - User's Manual: Remote (Distributed) Testing
JMeter Client/Server Remote Testing on Docker - Qiita
今回JMeterのdockerコンテナを作成するにあたり、justb4/docker-jmeterのv5.4(2022.06 時点の最新)を使用しました。
こちらのリポジトリをサーバにCloneします。
https://github.com/justb4/docker-jmeter
使い方についてはREADMEにわかりやすく記載されているため参照ください。
サーバにJMeterのdockerイメージをビルドします。
本来であればリポジトリ内のbuild.sh
を叩くだけでイメージをビルドしてくれるのですが、私の現場はプロキシ配下の環境であるため実際は下記のようにプロキシ情報をdocker buildコマンドに渡すよう少し手を入れています。
また、タイムゾーンもデフォルトではEurope/Amsterdam
となっているためAsia/Tokyo
に変更します。
#!/bin/bash
JMETER_VERSION="5.4"
IMAGE_TIMEZONE="Asia/Tokyo"
docker build --build-arg JMETER_VERSION=${JMETER_VERSION} \
--build-arg TZ=${IMAGE_TIMEZONE} \
--build-arg http_proxy=${proxy} \
--build-arg https_proxy=${proxy} \
-t "justb4/jmeter:${JMETER_VERSION}" .
適当に変更したらbuild.sh
を実行します。
Server 役のサーバ上で下記を実行。
実行すると Client からの命令を待ってくれます。
sudo docker run -it --rm \
-p20000:20000 \
justb4/jmeter:5.4 \
-s -n -j /dev/stdout \
-Dserver_port=20000 -Dserver.rmi.localport=20000 \
-Dserver.rmi.ssl.disable=true \
-Djava.rmi.server.hostname=$(host $(hostname)| awk '{print $4}') \
-Jmode=Statistical
-p20000:20000
20000 番ポートを空ける
-Dserver_port=20000 -Dserver.rmi.localport=20000
使用するポートを指定する
-Dserver.rmi.ssl.disable=true
SSLを無効化
-Djava.rmi.server.hostname=$(hostname -i | awk '{print $1}')
RMI(Remote Method Invocation)の設定。自身のホストサーバのIPアドレスを取得する
-Jmode=Statistical
Cleint - Server間の通信量が多いため Statistical を設定して通信量を削減
test.sh
から呼ばれるrun.sh
はdockerコンテナを起動させるシェルとなっています。
コンテナが JMeterのClientとして起動されるよう引数部分を修正します。
# JMeterClient の起動
./run.sh -Dlog_level.jmeter=DEBUG \
-Djava.rmi.server.hostname=$(hostname -i | awk '{print $1}') \
-Dclient.rmi.localport=20001 \
-Dserver.rmi.ssl.disable=true \
-Jremote_hosts=${server-IPAddress}:20000 \
-Jmode=Statistical \
-n -t test/test.jmx -l test/test.jtl \
-j test/jmeter.log \
-e -o report -r -X
-Dlog_level.jmeter=DEBUG
JMeterのログレベル
-Djava.rmi.server.hostname=$(hostname -i | awk '{print $1}')
RMI(Remote Method Invocation)の設定。自身のホストサーバのIPアドレスを取得する
-Dclient.rmi.localport=20001
デフォルトではポート番号が動的に使用されてしまうため固定化する
-Dserver.rmi.ssl.disable=true
SSLを無効化
-Jremote_hosts=${server-IPAddress}:20000
リモートサーバのIPアドレスとポート番号を指定(リモートサーバは20000ポートを空けます)
-Jmode=Statistical
Cleint - Server間の通信量が多いためStatisticalを設定して通信量を削減
-n
JMeterをCLIモードで実行
-t
JMeterのシナリオファイルを指定
-l
JMeterの結果ファイルを指定
-j
JMeterのログファイルを指定
-e
JMeter実行後にダッシュボードのレポートファイル作成
-o
ダッシュボードのレポートファイルを指定
-r
remote_hosts
で指定されたサーバでテストを実行
-X
テスト終了時にサーバを終了(ログアウト)する
test.sh
から呼ばれるrun.sh
を修正します。
#!/bin/bash
# Run JMeter Docker image with options
NAME="jmeter"
JMETER_VERSION="5.4"
IMAGE="justb4/jmeter:${JMETER_VERSION}"
# Finally run
docker run --rm --name ${NAME} --network=external-jmeter -i -v ${PWD}:${PWD} -w ${PWD} -p20001:20001 -p20002:20002 -p20003:20003 ${IMAGE} $@d
-p20001:20001 -p20002:20002 -p20003:20003
リモートサーバとやり取りするポートは最大3つ使われるためこのオプションでポートを空ける
-network=external-jmeter
JMeterのメトリクスをInfluxDBに送るためのdockerの使用ネットワーク ※別記事で説明します
test.sh
を実行しClientを起動するとServerに実行命令が送られJMeterが実行されます。
テスト終了まで待つとtest.sh
に指定したディレクトリにログやレポートファイルが作成されます。
レポートファイルについては下記を参照ください。すべて英語です。
Apache JMeter - User's Manual: Generating Dashboard Report
ちなみに、環境さえ整えればシェルを実行するだけなのでJenkinsジョブから実行させてレポートファイルもジョブから確認する、なんてこともできます。(いつかJenkinsについての記事も書けたら。。)
また別の記事でJMeterメトリクスをInfluxDBに送り、Grafanaでリアルタイムで結果を可視化させるようにする手順を紹介します。
ぼちぼち記事投稿できるようがんばります。