今までWebの負荷テストにJMeterを使っていましたが、秒間数百req/sとあまり高負荷をかけられなかったので、こちらの記事を見てtsungを使用することに決めました。
今回は単純に一つのMacクライアントから一つのWebサーバに負荷を掛けてみます。
Macで動かそうとすると色々ハマったので備忘録も兼ねて。
環境
MBP13インチ(Early 2015)
CPU: i7(3.1GHz 物理2コア)
メモリ: 8GB
$ tsung -v
Tsung version 1.6.0
インストール
$ brew install tsung # tsung本体
$ tsung -v
$ sudo cpan Template # Template-Toolkitのインストール
# インストール時の質問は全て[y]または[Enter]で答えれば大丈夫でした
Load Testing Rails 5 Action Cable with Tsungを参考にTemplate-Toolkitをインストールしましたが、それだけでは集計用プログラムを走らせる時に、
Can't locate Template.pm in @INC (you may need to install the Template module) (@INC contains: /Library/Perl/5.18/darwin-thread-multi-2level /Library/Perl/5.18 /Network/Library/Perl/5.18/darwin-thread-multi-2level /Network/Library/Perl/5.18 /Library/Perl/Updates/5.18.2 /System/Library/Perl/5.18/darwin-thread-multi-2level /System/Library/Perl/5.18 /System/Library/Perl/Extras/5.18/darwin-thread-multi-2level /System/Library/Perl/Extras/5.18 .) at /usr/local/lib/tsung/bin/tsung_stats.pl line 570.
というエラーメッセージが表示され、上手く動きませんでした。
brewでperlをインストールしていたので、集計用プログラムのperlのパスが違っていたのが原因でした。
$ which perl
で/usr/bin/perl
と表示された場合は以下の修正は不要です。
$ chmod u+w /usr/local/lib/tsung/bin/tsung_stats.pl # 書込権限付与
@@ -1,4 +1,4 @@
-#!/usr/bin/perl -w
+#!/usr/local/bin/perl -w
$ chmod u-w /usr/local/lib/tsung/bin/tsung_stats.pl # 書込権限削除
負荷テスト設定
負荷テストの設定はxmlファイルへ書き込みます。
$ git clone https://github.com/kurebio/mac-tsung.git
$ vi tsung.xml # テスト先サーバなどを指定
<?xml version="1.0"?>
<!DOCTYPE tsung SYSTEM "/usr/local/Cellar/tsung/1.6.0/share/tsung/tsung-1.0.dtd">
<tsung loglevel="notice" version="1.0">
<clients>
<client host='localhost' maxusers="500" use_controller_vm="true"/>
</clients>
<servers>
<server host="localhost" port="8000" type="tcp"/>
</servers>
<load>
<arrivalphase phase="1" duration="60" unit="second">
<users maxnumber="500" arrivalrate="100" unit="second"/>
</arrivalphase>
</load>
<sessions>
<session probability="100" name="http-test" type="ts_http">
<for from="1" to="10000" incr="1" var="counter">
<request> <http url="/test.json" method="GET" version="1.1"/> </request>
</for>
</session>
</sessions>
</tsung>
clients
<clients>
<client host='localhost' maxusers="500" use_controller_vm="true"/>
</clients>
ローカルのMacのみをクライアントとして使用します。
maxuser: このクライアントが走らせる最大ユーザー数
use_controller_vm: trueで最大オープンソケット数の問題を解決するためのErlang virtual machineを使用しません。参考
servers
<servers>
<server host="localhost" port="8000" type="tcp"/>
</servers>
localhost:8000へ向けて負荷テストを行います。
load
<load>
<arrivalphase phase="1" duration="60" unit="second">
<users maxnumber="500" arrivalrate="100" unit="second"/>
</arrivalphase>
</load>
arrivalphase: 最初のフェーズで(二つ目以降のフェーズはありませんが)duration秒間アクセスし続けます。
unitにはsecond, minute または hourが入り、現バージョンでは50日弱程度まで設定出来ます。
6.4.3. Duration of the load test
users: 同時アクセスを行う数(ユーザー)を、最大arrivalrateユーザー/unitずつ増やし、maxnumberまで増加させます。
増加量は必ずしもarrivalrateの値になるのではなく、クライアントの負荷によっては増加量が減少します。
最大数は$ ulimit -n
の数に依存するので、必要に応じてmacOS Sierraでulimitを変更する方法などで調整しましょう。
durationに達するか、ユーザーがmaxnumberまで達したらユーザーの増加が止まり、全ユーザーのリクエストが完了次第プログラムが終了します。リクエストが終了するまで止まらないため、リクエスト実行時間=durationではありません。
sessions
<sessions>
<session probability="100" name="http-test" type="ts_http">
<for from="1" to="10000" incr="1" var="counter">
<request> <http url="/test.json" method="GET" version="1.1"/> </request>
</for>
</session>
</sessions>
session probability: 100%の確率でこのセッションを使用します(複数セッションがある場合は合計が100になるよう設定します)。
probabilityの変わりにweightを用いると、weight="1"とweight="2"を設定した2つのセッションに、それぞれ1:2の割合でアクセスを割り振る、ということもできます。
Tsungで負荷テストしよう(3) - リアルな負荷のためのTips
for: この場合for(int counter = 1; counter <= 10000, counter++)
のような意味です。
counterはリクエストURLに使用出来ます。
<http url="/page?id=%%_counter%%"></http>
その他のループや条件分岐は以下より。
6.7.5. Loops, If, Foreach
request: 1人のユーザーがどのエンドポイントへリクエストするか指定します。
上記内容を総合すると、ローカルサーバのJSONに10,000回アクセスしようとする最大500人のユーザーが毎秒100人くらい現れる、という内容になります。
負荷テスト実行
$ tsung -f ./tsung.xml -l log start # 負荷テスト実行
Starting Tsung
Log directory is: ~/tsung/log/[YYYYMMDD-HHMM]
[os_mon] cpu supervisor port (cpu_sup): Erlang has closed
# 最新のログを集計し、レポートをブラウザで開く 上記負荷テスト実行と繋げても良し
$ cd ./log/`ls -t log | head -n 1` && \
/usr/local/lib/tsung/bin/tsung_stats.pl && \
open report.html && \
cd ../../
結果
Mac→同ホスト内nginxの静的ファイル
Code | Highest Rate | Mean Rate | Total number |
---|---|---|---|
200 | 27133.1 / sec | 13299.37 / sec | 5000000 |
自ホストへのリクエストですが、最大秒間27133req/sでリクエストを行えました!
Mac→リモートホスト(ConohaVPS 32G/12v)内nginxの静的ファイル
Code | Highest Rate | Mean Rate | Total number |
---|---|---|---|
200 | 11300.4 / sec | 5896.29 / sec | 499997 |
負荷を考え、リクエスト数を1ユーザー当り1,000に減らしました。
この数値はtsungやnginxの限界というより、自宅回線やConohaのネットワークの限界(100Mbps)のようです。
リモート側のCPU使用率は10%くらいで、トラフィックは90Mbps前後でした。
3回ほどエラーで失敗しているのは、回線の逼迫が原因かと思います。
Mac→リモートホスト(ConohaVPS 32G/12v)内Wordpress(初期状態, kusanagi使用, cache未使用)TOPページ
Code | Highest Rate | Mean Rate | Total number |
---|---|---|---|
200 | 857.8 / sec | 602.67 / sec | 50000 |
リクエスト数を1ユーザー当り100に減らし、ネットワークの負荷を下げるためテンプレートファイルの出力を3バイトにし、php-fpmのchildrenをmin100~max500に設定しました。
リモート側のCPU使用率は60%弱くらいでした。
この辺りはKUSANAGI for AWSの太い回線で、本番用のプラグインも入れてテストしたいですね。
JMeter参考
ケース | max(req/s) | mean(req/s) |
---|---|---|
Mac→ローカル | 1055.4 | 456.3 |
Mac→リモート静的ファイル | 606 | 346.9 |
Mac→リモートWordpress | 610.9 | 358.5 |
まとめ
Macのノート用の低消費電力CPUでも数万req/sを叩き出せて満足です。
設定次第でPOSTリクエスト、認証ページへのアクセス、DBサーバーへのクエリ、レスポンスのチェックなど、自由度の高いテストが出来るので、色々試してみたいです。
今回はMaxを測るため瞬間的にリクエスト数を増やしましたが、実務で使う場合は1週間の間毎秒100人ずつアクセスさせ、たまにユーザー数が10倍になる、といった設定で走らせた方が妥当かもしれません。
VPSなどに負荷を掛ける場合は他の利用者のことも考え、CPUやトラフィックの数値を見ながら大量に長時間リソースを消費しないよう行いましょう。