はじめに
ハンズラボ [Advent Calendar 2020](https://qiita.com/advent-calendar/2020/handslab"Advent Calendar 2020") 15日目の記事になります。
2020/12/01にハンズラボ株式会社に入社しました@anakagawa1114です!
入社後わずか2週間でこのような記事を書く機会をいただけて嬉しく思います。
今後も何かしら技術系の記事を定期期的にあげられればと思いますので、
宜しくお願い致します。
さて、今回の記事は負荷試験ツールJMeterについてとなります。
丁度現在タスクで負荷試験ツールの調査をやっており、それの備忘録も兼ねておりますので、
技術的に正しくなかったり稚拙な部分があるかもしれませんが、生暖かい目で見守っていただければ幸いです。
JMeterとは
Java製のWebページ負荷テストツール
オススメの使い方はGUIでシナリオ作成してCUIで実施みたい
※ GUIはMac, WIndows両方対応
公式:https://jmeter.apache.org/
最新版DL:http://jmeter.apache.org/download_jmeter.cgi
構築環境
JMeter GUI環境 (テストシナリオ作成環境)
- MacOS 10.15.7
- JMeter 5.4
JMeter CUI環境 (テストシナリオ実行環境 Master/Slave)
- CentOS 7.9
- JMeter 5.4
- Java 1.8.0
Target Webサーバ (負荷をかけるWebサーバ)
- CentOS 7.9
- Apache 2.4
アーキテクチャ図
- VirtualBox内のVMにDockerコンテナを設置し各環境を構築
GUI環境作成編
Javaインストール
- JMeterが対応しているJavaを入れる必要があります
- JMeter 5.4なのでJava 8相当
- JMeter 5.4 要件:https://jmeter.apache.org/download_jmeter.cgi
- Java8 SDK https://www.oracle.com/jp/java/technologies/javase/javase-jdk8-downloads.html
anakagawa$ java -version
java version "1.8.0_271"
Java(TM) SE Runtime Environment (build 1.8.0_271-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.271-b09, mixed mode)
JMeter実行
- JMeterをダウンロードし実行する
- 最新版:http://jmeter.apache.org/download_jmeter.cgi からダウンロード
- 解凍しapache-jmeter-5.4/binの中にある【jmeter】をダブルクリック
- 起動に成功すると下記画面が出る
- このままでも良いのですがついでに日本語化してみます
- メニュー画面の【Options】→【Choose Language】→【Japanese】
シナリオ作成
- スレッドの設定作成&設定
- スレッド数:同時に実行するテストの回数 今回は1回
- Ramp-Up(秒):スレッドグループが起動するまでの時間です 今回は1秒で1個のスレッドグループが起動します
- ループ回数:各スレッドが一連の処理を実施する回数です 今回は100回アクセスする設定
- スレッドグループにHTTPリクエストを作成
- 右クリックで【追加】→【サンプラー】→【HTTPリクエスト】
- HTTPリクエストを設定
- 接続先は要件に合わせて設定
- 今回はTOPページにアクセスが集中する想定で実験するのでGETで/index.htmlを指定
- 必要な設定をしたら画面下部の【追加】を選択
ターゲットWebサイト
- VirtualBox上Dockerコンテナ内にあるWebサーバにテストを実施
- 下記Webサーバコンテナに転送(構築方法は割愛)
[root@Tool-Test ~]$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ccd384fc68a4 centos:centos7 "/sbin/init" 4 days ago Up 11 hours 0.0.0.0:8080->80/tcp httpd
IP Address : 192.168.56.3:8080
ドキュメントルート:/index.html
リクエスト:GET
- 統計レポートの追加(結果を集計するやつ)
- HTTPリクエストの上で右クリックし【追加】→【リスナー】→【統計レポート】で作成
- ここまでできたらテストを一度保存します
- 【ファイル】→【テスト計画を保存】を選択し保存します(後でCUIで動作させる時に使います)
GUIで動作確認
- テスト実施
- 画面上の【▶】(開始)を押す
- 押すと最初に設定したスレッドの設定の通り100回アクセスされている(画面上は)
- Webサーバ側で確認
- VirtualBoxのホストネットワークを経由するのでアクセスログの接続元が【192.168.56.1】になる
[root@ccd384fc68a4 /]# ionice -c2 -n7 nice -n19 egrep '10/Dec/2020:06' /var/log/httpd/access_log | awk '{print $4}'| cut -c 2-18 | sort | uniq -c
100 10/Dec/2020:06:25
[root@ccd384fc68a4 /]# cat /var/log/httpd/access_log | grep "10/Dec/2020:06" | head
192.168.56.1 - - [10/Dec/2020:06:25:26 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_271)"
192.168.56.1 - - [10/Dec/2020:06:25:26 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_271)"
192.168.56.1 - - [10/Dec/2020:06:25:26 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_271)"
192.168.56.1 - - [10/Dec/2020:06:25:26 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_271)"
192.168.56.1 - - [10/Dec/2020:06:25:26 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_271)"
192.168.56.1 - - [10/Dec/2020:06:25:26 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_271)"
192.168.56.1 - - [10/Dec/2020:06:25:26 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_271)"
192.168.56.1 - - [10/Dec/2020:06:25:26 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_271)"
192.168.56.1 - - [10/Dec/2020:06:25:26 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_271)"
192.168.56.1 - - [10/Dec/2020:06:25:26 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_271)"
-
無事サーバのアクセスログからもアクセスが確認できたので次はCUI編です
- 集計コマンドについては私の過去記事を参考にどうぞ
- https://qiita.com/anakagawa1114/items/56ee60ea720b83f8142f
CUI環境作成編
CentOS7
CentOS Linux release 7.9.2009
- Virtualbox&Dockerで作成(Virtualbox&Dockerの構築は割愛)
Javaインストール
yum install -y java
[root@24c7217afc90 opt]# java -version
openjdk version "1.8.0_272"
OpenJDK Runtime Environment (build 1.8.0_272-b10)
OpenJDK 64-Bit Server VM (build 25.272-b10, mixed mode)
JMeter ダウンロード&配置
- /opt配下に設置を想定
cd /opt
curl -O https://ftp.kddi-research.jp/infosystems/apache//jmeter/binaries/apache-jmeter-5.4.tgz
tar -xvzf apache-jmeter-5.4.tgz
- Path追加
vi ~/.bashrc
# apache jmeter
PATH=$PATH:$HOME/bin:/opt/apache-jmeter-5.4/bin
- Path反映&バージョン確認
source ~/.bashrc
[root@24c7217afc90 opt]# jmeter --version
Dec 09, 2020 6:55:24 AM java.util.prefs.FileSystemPreferences$1 run
INFO: Created user preferences directory.
_ ____ _ ____ _ _ _____ _ __ __ _____ _____ _____ ____
/ \ | _ \ / \ / ___| | | | ____| | | \/ | ____|_ _| ____| _ \
/ _ \ | |_) / _ \| | | |_| | _| _ | | |\/| | _| | | | _| | |_) |
/ ___ \| __/ ___ \ |___| _ | |___ | |_| | | | | |___ | | | |___| _ <
/_/ \_\_| /_/ \_\____|_| |_|_____| \___/|_| |_|_____| |_| |_____|_| \_\ 5.4
Copyright (c) 1999-2020 The Apache Software Foundation
※ ロゴの横に小さく5.4って書いてあります(わかりにくい)
JMeter実行(CUI Master)
- SSL設定
- 今回はHTTPであってHTTPSで実験しないので、SSLはOFFにする
- <JMeter Home Dir>/bin/jmeter.properties
server.rmi.ssl.disable=false → trueへ
- JMeterにシナリオを読み込ませて実行する
- GUI編で作成したシナリオファイル(.jmx)をJMeterサーバにコピーする
- JMeter実行時のオプションは下記の通り
--?
print command line options and exit
-h, --help
print usage information and exit
-v, --version
print the version information and exit
-p, --propfile <argument>
the jmeter property file to use
-q, --addprop <argument>
additional JMeter property file(s)
-t, --testfile <argument>
the jmeter test(.jmx) file to run
-l, --logfile <argument>
the file to log samples to
-i, --jmeterlogconf <argument>
jmeter logging configuration file (log4j2.xml)
-j, --jmeterlogfile <argument>
jmeter run log file (jmeter.log)
-n, --nongui
run JMeter in nongui mode
-s, --server
run the JMeter server
-H, --proxyHost <argument>
Set a proxy server for JMeter to use
-P, --proxyPort <argument>
Set proxy server port for JMeter to use
-N, --nonProxyHosts <argument>
Set nonproxy host list (e.g. *.apache.org|localhost)
-u, --username <argument>
Set username for proxy server that JMeter is to use
-a, --password <argument>
Set password for proxy server that JMeter is to use
-J, --jmeterproperty <argument>=<value>
Define additional JMeter properties
-G, --globalproperty <argument>=<value>
Define Global properties (sent to servers)
e.g. -Gport=123
or -Gglobal.properties
-D, --systemproperty <argument>=<value>
Define additional system properties
-S, --systemPropertyFile <argument>
additional system property file(s)
-f, --forceDeleteResultFile
force delete existing results files and web report folder if present before starting the test
-L, --loglevel <argument>=<value>
[category=]level e.g. jorphan=INFO, jmeter.util=DEBUG or com.example.foo=WARN
-r, --runremote
Start remote servers (as defined in remote_hosts)
-R, --remotestart <argument>
Start these remote servers (overrides remote_hosts)
-d, --homedir <argument>
the jmeter home directory to use
-X, --remoteexit
Exit the remote servers at end of test (CLI mode)
-g, --reportonly <argument>
generate report dashboard only, from a test results file
-e, --reportatendofloadtests
generate report dashboard after load test
-o, --reportoutputfolder <argument>
output folder for report dashboard
- 下記コマンドで実行(NoGUI&Test File指定)
[root@24c7217afc90 ~]# /opt/apache-jmeter-5.4/bin/jmeter -n -t /opt/apache-jmeter-5.4/test-case.jmx
Creating summariser <summary>
Created the tree successfully using /opt/apache-jmeter-5.4/test-case.jmx
Starting standalone test @ Thu Dec 10 08:05:19 UTC 2020 (1607587519993)
Waiting for possible Shutdown/StopTestNow/HeapDump/ThreadDump message on port 4445
summary = 100 in 00:00:00 = 534.8/s Avg: 0 Min: 0 Max: 31 Err: 0 (0.00%)
Tidying up ... @ Thu Dec 10 08:05:20 UTC 2020 (1607587520458)
... end of run
- Webサーバ側で確認
[root@ccd384fc68a4 /]# ionice -c2 -n7 nice -n19 egrep '10/Dec/2020:08:05' /var/log/httpd/access_log | awk '{print $4}'| cut -c 2-18 | sort | uniq -c
100 10/Dec/2020:08:05
[root@ccd384fc68a4 /]# cat /var/log/httpd/access_log | grep "10/Dec/2020:08:05" | head
172.17.0.2 - - [10/Dec/2020:08:05:20 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_272)"
172.17.0.2 - - [10/Dec/2020:08:05:20 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_272)"
172.17.0.2 - - [10/Dec/2020:08:05:20 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_272)"
172.17.0.2 - - [10/Dec/2020:08:05:20 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_272)"
172.17.0.2 - - [10/Dec/2020:08:05:20 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_272)"
172.17.0.2 - - [10/Dec/2020:08:05:20 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_272)"
172.17.0.2 - - [10/Dec/2020:08:05:20 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_272)"
172.17.0.2 - - [10/Dec/2020:08:05:20 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_272)"
172.17.0.2 - - [10/Dec/2020:08:05:20 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_272)"
172.17.0.2 - - [10/Dec/2020:08:05:20 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_272)"
CUIでも無事アクセスができていることを確認できました!
JMeter実行(CUI Slave経由)
-
Slave環境の作成
- 基本はMasterと同じ環境をコピーするだけで問題ない
-
SSLの設定
- Masterと同じで使用しない場合はMasterでやったSSL設定をやること
- <JMeter Home Dir>/bin/jmeter.properties
server.rmi.ssl.disable=false → trueへ
- jmeter-serverの自動起動設定の為下記の内容を追加
- /etc/rc.d/rc.local
/opt/apache-jmeter-5.4/bin/jmeter-server &
- /etc/rc.d/rc.localの実行権限を付与
sudo chmod +x /etc/rc.d/rc.local
- ファイルディスクリプタ上限を変更
sudo vi /usr/lib/systemd/system/rc-local.service
[Service]
LimitNOFILE=20000
$ sudo vi /etc/security/limits.conf
* soft nofile 20000
* hard nofile 20000
- カーネルパラメータ設定
- 下記を追加
sudo vi /etc/sysctl.conf
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_fin_timeout=5
- 設定の反映
sudo systemctl -p
- サーバ再起動後Jeater起動を確認
[root@JMeter-Slave01 /]$ ps auxfww | grep "jmeter"
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 48 0.0 0.0 15124 1436 ? S 10:03 0:00 /bin/sh /opt/apache-jmeter-5.4/bin/jmeter-server
root 52 0.0 0.0 15124 1524 ? S 10:03 0:00 \_ /bin/sh /opt/apache-jmeter-5.4/bin/jmeter -Dserver_port=1099 -s -j jmeter-server.log
root 85 0.2 4.8 3529028 188668 ? Sl 10:03 0:06 \_ /usr/bin/java -server -XX:+HeapDumpOnOutOfMemoryError -Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:G1ReservePercent=20 -Djava.security.egd=file:/dev/urandom -Duser.language=en -Duser.region=EN -jar /opt/apache-jmeter-5.4/bin/ApacheJMeter.jar -Dserver_port=1099 -s -j jmeter-server.log
- Slaveサーバを指定してテストを実行
- $ jmeter -n -t <シナリオファイル> -R <IPアドレス>
[root@JMeter-Master /]$ /opt/apache-jmeter-5.4/bin/jmeter -n -t /opt/apache-jmeter-5.4/test-case.jmx -R 172.17.0.3
Creating summariser <summary>
Created the tree successfully using /opt/apache-jmeter-5.4/test-case.jmx
Configuring remote engine: 172.17.0.3
Starting distributed test with remote engines: [172.17.0.3] @ Mon Dec 14 10:36:25 UTC 2020 (1607942185991)
Remote engines have been started:[172.17.0.3]
Waiting for possible Shutdown/StopTestNow/HeapDump/ThreadDump message on port 4445
summary = 100 in 00:00:00 = 423.7/s Avg: 0 Min: 0 Max: 10 Err: 0 (0.00%)
Tidying up remote @ Mon Dec 14 10:36:26 UTC 2020 (1607942186912)
... end of run
- Webサーバ側で確認
[root@ccd384fc68a4 /]# ionice -c2 -n7 nice -n19 egrep '14/Dec/2020:10:36' /var/log/httpd/access_log | awk '{print $4}'| cut -c 2-18 | sort | uniq -c
100 14/Dec/2020:10:36
[root@ccd384fc68a4 /]# cat /var/log/httpd/access_log | grep "14/Dec/2020:10:36" | head
172.17.0.3 - - [14/Dec/2020:10:36:26 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_272)"
172.17.0.3 - - [14/Dec/2020:10:36:26 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_272)"
172.17.0.3 - - [14/Dec/2020:10:36:26 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_272)"
172.17.0.3 - - [14/Dec/2020:10:36:26 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_272)"
172.17.0.3 - - [14/Dec/2020:10:36:26 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_272)"
172.17.0.3 - - [14/Dec/2020:10:36:26 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_272)"
172.17.0.3 - - [14/Dec/2020:10:36:26 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_272)"
172.17.0.3 - - [14/Dec/2020:10:36:26 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_272)"
172.17.0.3 - - [14/Dec/2020:10:36:26 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_272)"
172.17.0.3 - - [14/Dec/2020:10:36:26 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "Apache-HttpClient/4.5.12 (Java/1.8.0_272)"
SlaveサーバのIPアドレス(172.17.0.3)から100回アクセスが来てることを確認できました!
最後に
検証は以上となります!
今まで負荷試験ツールというとWeb上でできる簡単な物しか使ったことがなかったのですが、今回始めてアプリで実施するに辺りJMeterの設定やSlaveの設定など、
若干躓く所がありましたが、ツールとしては非常に構築しやすいと思いました!
まだ、いくつか負荷試験ツールを検証する予定なので、余力があればまた記事としてあげたいと思います!
最後まで読んでいただき有難うございました!
また次の記事でお会いしましょう!!