WEBサーバーの負荷テストツールを使ってみた　ab, weighttp, Tsung

# **はじめに**

余っていたPCをLinux (CentOS 7.5.1804)化したので、[自作multithread化lighttpd](https://github.com/developer-kikikaikai/lighttpd_multithread)に対していくつか負荷テストツールを試してみました。
その際に使用した各ツールのインストール方法、使い方のご紹介です:+1:

インストール環境は全てVirtualBox上のUbuntu18.04, 4core, メモリ8GByteになります。
今回は**ab**、**weighttp**、 **Tsung**の3ツールを試してみました。
ほんとはJMeterも試したかったのですが、3種類使ってみてお腹いっぱいになったので記事の紹介だけにしておきます。

# **測定の前に: リクエストPCの環境設定**

各ツールどれもHTTPリクエストを大量に送るため、**ソケットの上限を上げておく**必要があります。

私は以下を追加しました。
1./etc/sysctl.confに以下を追加し、

```
net.ipv4.tcp_max_syn_backlog = 20480
net.core.somaxconn=20480
```

2./etc/security/limits.confに追加

```
net.ipv4.tcp_max_syn_backlog = 20480
net.core.somaxconn=20480
```

準備が出来たら紹介行きましょう！:laughing:	

----

# **ab**

apacheインストール時にデフォルトでインストールされているシンプルな負荷テストツールです。
apacheを利用している方はそのまま利用できるので楽ですね:grin:

## **インストール**

apt, yumが使える環境ならapacheをインストールすればOKです。
今回は環境構築時にaptが通らなかった(と思い込んでた)ので、[こちらのサイト](https://weblabo.oscasierra.net/install-apache24-1/)を参考に、コードからインストールしました。

**1.aprのインストール**

[apache apr](http://ftp.riken.jp/net/apache//apr/)からaprとapr-utilの最新版をダウンロードし、ビルドします。

```
wget http://ftp.yz.yamagata-u.ac.jp/pub/network/apache//apr/apr-1.6.3.tar.gz
tar xvzf apr-1.6.3.tar.gz
cd apr-1.6.3 && ./configure && make && sudo make install
```

成果物は/usr/local/apr/にインストールされます。次のビルドに使うので覚えておきましょう。

**2.apr-utilのインストール**

同じく[apache apr](http://ftp.riken.jp/net/apache//apr/)からapr-utilの最新版をダウンロードし、ビルドします。
ここで、./configure時に**--with-apr=/usr/local/apr/**を設定する必要があるので注意です。

```
wget http://ftp.yz.yamagata-u.ac.jp/pub/network/apache//apr/apr-util-1.6.1.tar.gz
tar xvzf apr-util-1.6.1.tar.gz
cd apr-util-1.6.1
./configure --with-apr=/usr/local/apr/
make && sudo make install
```

こちらの成果物も/usr/local/apr/にインストールされます。これも次のビルドに使います。

**3.apache httpdのインストール**

[apache公式のリンク先](http://ftp.riken.jp/net/apache//httpd/)から最新版をダウンロードし、ビルドします。
ここで、./configure時に**--with-apr=/usr/local/apr/ --with-apr-util=/usr/local/apr**を設定する必要があります。

```
wget http://ftp.jaist.ac.jp/pub/apache//httpd/httpd-2.4.34.tar.gz
cd httpd-2.4.34
./configure --with-apr=/usr/local/apr/ --with-apr-util=/usr/local/apr
make && sudo make install
```

ソースコンパイルの場合、デフォルトでは**/usr/local/apache2/**にパッケージがインストールされます。

## **使用方法**

使い方は以下です。URLはhttpから記載します。

```
/usr/local/apache2/bin/ab -n リクエスト数 -c 同時コネクション数 http://localhost/index.html
```

## **実行結果**

こんな感じに成功したリクエストの結果がどどーっ:dash:と表示されます。

```
# This is ApacheBench, Version 2.3 <$Revision: 1826891 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.1.1 (be patient)
Completed 500 requests
Completed 1000 requests
Completed 1500 requests
Completed 2000 requests
Completed 2500 requests
Completed 3000 requests
Completed 3500 requests
Completed 4000 requests
Completed 4500 requests
Completed 5000 requests
Finished 5000 requests
```

全てのリクエストが成功したら、結果が表示されます。

これはHTTP response情報。

```
Server Software:        lighttpd/1.4.49-devel-5678a40
Server Hostname:        192.168.1.1
Server Port:            80

Document Path:          /index.html
Document Length:        1150 bytes
```

こちらは測定結果がまとめられたものです。性能としてわかりやすいのは*Time taken for tests*, *Time taken for tests*辺りですかね。
ここでは5000リクエストをトータル2.929秒、秒間1707リクエストの間隔で捌いているのがわかります。

```
Concurrency Level:      5000
Time taken for tests:   2.929 seconds
Complete requests:      5000
Failed requests:        0
Total transferred:      6885000 bytes
HTML transferred:       5750000 bytes
Requests per second:    1707.25 [#/sec] (mean)
Time per request:       2928.695 [ms] (mean)
Time per request:       0.586 [ms] (mean, across all concurrent requests)
Transfer rate:          2295.78 [Kbytes/sec] received
```

こちらは実際のTCP接続時間ですね。

```
Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0  338 408.0    128    1243
Processing:     0  521 530.3    400    2353
Waiting:        0  521 530.2    400    2353
Total:         14  859 683.7    654    2568
```

こちらは全リクエストの何%がどのくらいの時間で処理されたかがわかります。

```
Percentage of the requests served within a certain time (ms)
  50%    654
  66%   1014
  75%   1421
  80%   1491
  90%   1849
  95%   2180
  98%   2488
  99%   2514
 100%   2568 (longest request)
```

見方の詳細は[Apache Benchの結果の見方](https://qiita.com/nnmr/items/2be82691e19da261c4e4)が丁寧だったので参考にしてみてください。

また、自分の環境だと途中でRequestがエラーになるとそこで止まってしまい、結果の表示をしてくれませんでした。ちょっと残念。

```
# This is ApacheBench, Version 2.3 <$Revision: 1826891 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.1.1 (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
apr_socket_recv: Connection reset by peer (104)
Total of 9842 requests completed
```

なので、測定するならPCを分け、sshを利用したスクリプトを組むのがベターだと思います。(凄いべた書きですがw

```shell:ab_c10k.sh
REQUEST=3334
CONNECTION=3334
URL=http://192.168.1.1/index.html
/usr/local/apache2/bin/ab -n ${REQUEST} -c ${CONNECTION} ${URL} &
echo "/usr/local/apache2/bin/ab -n ${REQUEST} -c ${CONNECTION} ${URL}" | ssh -i host_rsa 192.168.1.150 &
echo "/usr/local/apache2/bin/ab -n ${REQUEST} -c ${CONNECTION} ${URL}" | ssh -i host_rsa 192.168.1.244
```

----

# **weighty**

weighttpは、Webサーバlighttpdの開発者が実装したWebサーバの性能測定ツールです。
abと似たオプションですが、マルチスレッドでの測定による高速で安定した動作が期待できます。

## **インストール**

[こちらの記事](https://qiita.com/developer-kikikaikai/items/ff55b8895276bed80fef)で記載した通りなので省略。

## **使用方法**

使い方は以下です。httpは省略して使用します。(httpsは非サポート)

```
weighttp -n リクエスト数 -c 同時接続クライアント -t クライアントが使用するスレッド数 -k(キープアライブの場合) localhost/index.html
```

## **実行結果**

このような感じで、結果を性能に絞って出力している印象です。シンプルで見やすいですね:+1:

```
$ weighttp -n 5000 -c 5000 -t 4 192.168.1.1/i
ndex.html
weighttp 0.4 - a lightweight and simple webserver benchmarking tool

starting benchmark...
spawning thread #1: 1250 concurrent requests, 1250 total requests
spawning thread #2: 1250 concurrent requests, 1250 total requests
spawning thread #3: 1250 concurrent requests, 1250 total requests
spawning thread #4: 1250 concurrent requests, 1250 total requests
progress:  10% done
progress:  20% done
progress:  30% done
progress:  40% done
progress:  50% done
progress:  60% done
progress:  70% done
progress:  80% done
progress:  90% done
progress: 100% done

finished in 7 sec, 256 millisec and 279 microsec, 689 req/s, 926 kbyte/s
requests: 5000 total, 5000 started, 5000 done, 5000 succeeded, 0 failed, 0 errored
status codes: 5000 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 6885000 bytes total, 1135000 bytes http, 5750000 bytes data
```

同じ5000コネクションでも`ab`はトータル2.929秒、こちらは7.256秒と結構性能が変わりますね:sweat:
progressの進みを見ていると、瞬間的なレスポンスの進みは`ab`よりも多い気がするけど、そこかでHTTPサーバー側がどんづまってるのかな。
疑うところは色々ありますが、ポートフォワード出来るハブ等道具がないので置いときましょう。:weary:

**HTTPサーバーの性能比較が目的なら、使用するツールは合わせないといけませんね!**

----

# **Tsung**

こちらは多機能で面白いツールで、複数のWebクライアントPCから1サーバーへの負荷テストを実施することが出来る(はずの)ツールです:open_mouth:
この負荷テストはリクエストの種類や送信タイミングをコントロール出来たり、結果の見え方もテスト時のクライアント側のCPU負荷等が見えたりと色々とかゆい所に手が届いている感があります:bowtie:

Tsungは以下のような2種類のクライアント側PCを利用して試験を実施します。

1. Tsungを使用してテストを開始するPC
2. リクエスト分散の為に1のPCからsshログインして利用されるPC

ここでは便宜上1, 2をそれぞれ**テストサーバーPC**, **クライアントノードPC**と呼ぶことにします。

## **インストール**

### **テストサーバーPC、クライアントノードPC共通**

まずはerlangとperlをインストールします。(ここで普通にaptが使えることに気付く私:cold_sweat:

```
apt install erlang perl
```

### **テストサーバーPCのみ**

**1.テスト実行の為に`tsung`をインストール**

[tsungサイト](http://tsung.erlang-projects.org/dist/)から最新コードをダウンロードしてビルド。2018/08/11現在は1.7.0が最新でした。

```
wget http://tsung.erlang-projects.org/dist/tsung-1.7.0.tar.gz
tar xvzf tsung-1.7.0.tar.gz
cd tsung-1.7.0 && ./configure && make && sudo make install
```

**2.実行結果解析の為のツールをインストール**

この結果解析の為の環境構築が地味に面倒でした。

**2.1.Template Toolkitのインストール**

まずは[Template Toolkit Downloads](http://www.tt2.org/download/index.html)を参考に、Template Toolkitをインストールします。

```
wget http://cpan.org/modules/by-module/Template/Template-Toolkit-2.26.tar.gz
tar zxf Template-Toolkit-2.26.tar.gz
cd Template-Toolkit-2.26
perl Makefile.PL
make
sudo make install
```

**2.2 gnuplotのインストール**

結果をグラフ化するため`gnuplot`も[gnuplot公式のファイル](http://sourceforge.net/projects/gnuplot/files/gnuplot/)からダウンロードし、インストールします。2018/08/11現在の最新は5.2.4。
ただそのままインストールするだけだとpngファイルが作れないので、以下パッケージを先にインストールします。

```
sudo apt install libcairo2-dev libpango1.0-dev libgd-dev
```

その後ソースをコンパイル、インストール。

```
wget http://sourceforge.net/projects/gnuplot/files/gnuplot/5.2.4/gnuplot-5.2.4.tar.gz
tar xvzf gnuplot-5.2.4.tar.gz 
cd gnuplot-5.2.4
./configure && make && sudo make install
```

これで準備完了:+1:

## **実行**

### **負荷テストシナリオ設定**

まずは負荷テストの設定を記載するxmlファイルを作成します。

```xml:tsung.xml
<?xml version="1.0"?>
<!DOCTYPE tsung SYSTEM "/usr/share/tsung/tsung-1.0.dtd">
<tsung loglevel="notice" version="1.0">

<clients>
<client host="localhost" weight="1" maxusers="10000" use_controller_vm="true">
</client>
</clients>

<servers>
<server host="192.168.1.1" port="80" type="tcp"/>
</servers>

<load>
<arrivalphase phase="1" duration="1" unit="minute">
<users maxnumber="10000" arrivalrate="8" unit="second"/>
</arrivalphase>
<arrivalphase phase="2" duration="1" unit="minute">
<users maxnumber="10000" arrivalrate="8" unit="second"/>
</arrivalphase>
</load>

<sessions>
<session probability="100" name="session1" type="ts_http">
<for from="1" to="10000" var="i">
<request> <http url="/index.html" method="GET" version="1.1"/> </request>
</for>
</session>
</sessions>
</tsung>
```

各要素の概要は以下です。

|要素|概要|
|:---|:---|
|clients|クライアントノードPCの指定|
|servers|HTTPサーバーの設定|
|load|クライアントノードPCがHTTPサーバーへアクセスするタイミングと速さの設定|
|sessions|クライアントノードPCがHTTPサーバーへアクセスする際のリクエストの設定|

**clients**

複数指定が可能。。。なはずなんですが、私の環境ではうまく扱えませんでした:sweat_smile:。う～む、VMのせいかな

とりあえずわかっている必須項目だけ書いておきます。

- ホスト名の設定が必要

**クライアントノードPCの指定はホスト名**で行います。その為名前解決必須。
名前解決はテストサーバーPCで出来ればいいだけなので、テストサーバーPCの`/etc/hosts`に直書きしちゃいましょう。
例えばlocalhost1, localhost2をクライアントノードPCのホスト名にするなら以下のような感じで。

```conf:/etc/hosts
192.168.1.150 localhost1
192.168.1.244 localhost2
```

- 鍵を使ったsshログイン設定が必要

テストはsshで実行するため、各クライアントノードPCへは鍵でのキー入力無しssh接続を行う必要があります。

これで全部エラーが取れたんですが、明らかに複数指定するとrequestが飛んでいない…:dizzy_face:
まあ1クライアントで使っても面白いツールなので先に行きます。

**load**

arrivalphase内の記載で、クライアントがどのくらいの時間(durationとunit)、どんな風にHTTPサーバーへアクセスを繰り返し行うのか(usersの設定)指定が出来ます。
例えば以下なら1分間、最大10000回アクセスを8秒間隔で繰り返します。

```xml:tsung.xml
<arrivalphase phase="1" duration="1" unit="minute">
<users maxnumber="10000" arrivalrate="8" unit="second"/>
</arrivalphase>
```

arrivalphaseはphaseの指定が可能で、色んなパターンの負荷試験を組み合わせるならphase 2, 3と追加すればOK！

**sessions**

loadで設定された1アクセス毎に行うリクエストを設定します。
以下設定の場合、`<for>`タグで指定した10000回分、`<request>`タグで指定したindex.htmlへのGETリクエストを繰り返し送信します。

```xml:tsung.xml
<session probability="100" name="session1" type="ts_http">
<for from="1" to="10000" var="i">
<request> <http url="/index.html" method="GET" version="1.1"/> </request>
</for>
</session>
```

上のloadとsessionを合わせると、**「1分間の間に、8秒間隔で最大10,000クライアントが、10,000回index.htmlへのGETリクエストを送信する」**というテストになります:clap:
凄い負荷テストのシナリオが1xmlファイルでかけちゃうわけですね。


また、sessionも複数指定が可能です。その場合はprobabilityが合計100になるよう各sessionに割り振ります。
(probabilityで指定された確率で、requestを繰り返すという感じですね)

### **実行**

ファイルが出来たらTsungコマンドでテストを実施します。-lでログ出力先を、-fでxmlファイルを指定します。-lを指定しない場合は~/.log/配下にログが出力されます。

```
tsung -f tsung.xml start
```

成功するとこのような感じでログが表示されます。

```
# tsung -f tsung.xml start
Starting Tsung
Log directory is: /root/.tsung/log/20180811-2024
[os_mon] memory supervisor port (memsup): 
Erlang has closed
[os_mon] cpu supervisor port (cpu_sup): Erlang has closed
```

## **実行結果**

実行結果はコマンドを利用してHTMLのレポートを作成する形を取っています。
[こちらの記事](https://qiita.com/Hexa/items/323d69ee19a68f217191#%E3%83%AC%E3%83%9D%E3%83%BC%E3%83%88%E3%81%AE%E4%BD%9C%E6%88%90)を参考にレポート作成。

ログの場所に移動して`tsung_stats.pl`を実行。私の環境では`/usr/lib/tsung/bin/tsung_stats.pl`にインストールされていました。

```
cd ./log/20180811-1129/
/usr/lib/tsung/bin/tsung_stats.pl --stats tsung.log
```

HTMLのレポートにはこのような**数値のまとめから**

<img width="1000" alt="status.png" src="https://qiita-image-store.s3.amazonaws.com/0/252277/1b438b8e-928e-9880-0d98-3f93e6b8711b.png">

**視覚化されたグラフまで**出力されます！いいね:+1:

<img width="1000" alt="graph.png" src="https://qiita-image-store.s3.amazonaws.com/0/252277/ac961dec-6b28-f146-2d28-5ad9d40ee0b1.png">

さらに、結果にはHTTPサーバー側の性能以外にも**テストサーバーPC側のCPU使用率なども含まれる**ため、遅延が発生した場合にクライアント側の原因がないかもわかります:satisfied:
色々と楽しいツールでした。

----

# **その他ツールの紹介**

## **JMeter**

こちらは実際試していないので記事の紹介だけ。
[負荷テスト・パフォーマンス測定ツールのJMeterのインストールと簡単な使い方](https://qiita.com/PlanetMeron/items/a604645d6f89b6ce3a14)

GUIベースで操作を登録し、登録した操作に対する繰り返し負荷試験を実施することが可能なようです。Tsungもそうですが複雑な組み合わせリクエスト試験が可能になります。
GUIベースなので、細かなシナリオ作りがしやすいかもしれませんね。

## **h2load**

@tenmyo さんからのコメントより追記

abの使い勝手そのままに、weighttpの良さを受け継ぎつつ**HTTP/2の計測が出来る**。HTTP/2の測定が出来るのは面白いですね。

[h2load を使おう - あどけない話](http://d.hatena.ne.jp/kazu-yamamoto/20151225/1451287148)

環境構築された方の記事
[http/2ベンチマークツール「h2load」をインストール](https://www.meganii.com/blog/2016/07/17/install-h2load/)

さりげにwrkなんていうまた別のベンチマークツールもあったり。ベンチマークの世界も幅広いですね。

## **参考**

大元のab, tsung参考サイト
[サーバの負荷テストのための、何百万ものHTTPリクエストを発生させる方法](https://postd.cc/how-to-generate-millions-of-http-requests/)

abの参考
[Apache httpd 2.4 をソースからインストールする手順 (CentOS/RedHat)](https://weblabo.oscasierra.net/install-apache24-1/) (CentOSでの手順でしたが、ubuntuでも行けました)
[Apache Benchの結果の見方](https://qiita.com/nnmr/items/2be82691e19da261c4e4)


tsungの参考
[Macとtsungで手軽に数千~数万req/sのHTTP負荷テスト](https://qiita.com/kurebio/items/2eac819962f7886bae4a)
[Tsung で負荷試験](https://qiita.com/Hexa/items/323d69ee19a68f217191)
　gnuplotのインストール [can't exec gnuplot tsung](http://tutslaptrinh.com/tutorial-detail/cant-exec-gnuplot-tsung)
　gnuplotへのpng追加 [Terminal “png” missing when using Gnuplot](https://stackoverflow.com/questions/22816030/terminal-png-missing-when-using-gnuplot)