Webサーバー向けのベンチマークツールを使ってみよう(前編)――Apache BenchとSiege

WebサーバーやWebサービスの公開前には、そのサーバーがどの程度のアクセスにまで耐えられるかを事前に調査しておくことが好ましい。本記事では、こういった調査の際によく使われる「Apache Bench」および「Siege」というツールの使い方を紹介する。

サービスの公開前に行っておくべき負荷テスト

昨今では低価格サーバーでも高性能化が進んでおり、静的なページを表示するだけのWebサーバーや比較的負荷の少ない処理を行うようなWebアプリケーションでは、1台のサーバーのみでそれなりの規模のアクセスに耐えられるようになっている。とはいえ、CPUの性能やメモリ容量、ストレージの種類などによってアプリケーションのピーク性能は変動するため、単純にハードウェアの性能や使用するソフトウェアといった情報だけでどの程度までのアクセスを捌けるのかを判断することは難しい。実際、負荷をかけてみたら「想定していたレベル」よりもスループットが低かった、という例は少なくない。そのため、あらかじめサーバーに対して負荷テストを行い、想定している最大アクセスに耐えられるかどうかを調査しておくことが重要となる。

こういった負荷テストの手法や、それを実現するためのツールにはさまざまなものがあるが、本記事ではそのなかでも使いやすく汎用性も高い「Apache Bench」と「Siege」、そして複雑なテストケースにも対応できる「Apache Jmeter」、JavaScriptの実行タイムまでも計測できる「wbench」について、2回に渡って紹介する(図1)。

図1 Apache Benchの実行結果画面

図1 Apache Benchの実行結果画面

手軽に利用できるベンチマークツール「Apache Bench」

まず紹介するのは、手軽なベンチマークツールとして広く利用されているコマンドラインツール「Apache Bench」(ab)だ。Apache BenchはApache HTTP Serverに同梱されているため、Apache HTTP Serverが利用できる環境であればほとんどの場合ですぐに利用できる。Apache HTTP Serverに付属するツールではあるが、Webサーバーにリクエストを送信してその結果を集計するというシンプルなツールであるため、Apache HTTP Server以外のWebサーバーもテスト可能だ。

Apache Benchで実行できるテストは非常にシンプルで、指定したURLに対し高い頻度で連続アクセスを行う、というだけだ。対象とできるURLは1つだけなので複雑な遷移などはチェックできないが、サイトのトップページなどアクセスが多いと思われるページや、負荷の高いと思われるページがどれだけのアクセスに耐えられるかを調べるといった用途で利用できる。

Apache Benchの基本的な使い方

Apache Benchは「ab」というコマンドとして提供される。通常は「-c」や「-n」オプションを使い、URLとともに同時に発生させるリクエスト数、総リクエスト数などを指定して実行する。

ab -c <同時リクエスト数> -n <総リクエスト数> <URL>

「同時リクエスト数」は、同時に接続を行うクライアントの数に相当する。たとえば「http://localhost/」というURLに対し同時に10リクエストを発生させ、トータルで10000リクエストを行う場合のオプションとその実行結果は次のようになる。この場合、各クライアントはそれぞれ1000リクエストを送信することになる。また、ここではベンチマーク対象とするマシン上でApache Benchを実行している。

$ ab -c 10 -n 10000 http://localhost/
This is ApacheBench, Version 2.3 <$Revision: 1706008 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (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
Completed 10000 requests
Finished 10000 requests


Server Software:        Apache/1.3.42
Server Hostname:        localhost
Server Port:            80

Document Path:          /
Document Length:        111114 bytes

Concurrency Level:      10
Time taken for tests:   11.054 seconds
Complete requests:      10000
Failed requests:        0
Total transferred:      1114673762 bytes
HTML transferred:       1111140000 bytes
Requests per second:    904.68 [#/sec] (mean)
Time per request:       11.054 [ms] (mean)
Time per request:       1.105 [ms] (mean, across all concurrent requests)
Transfer rate:          98479.32 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       1
Processing:     3   11   6.0      9      72
Waiting:        2    8   5.3      6      65
Total:          4   11   6.0      9      72

Percentage of the requests served within a certain time (ms)
  50%      9
  66%     12
  75%     13
  80%     14
  90%     18
  95%     23
  98%     28
  99%     33
 100%     72 (longest request)

この結果からは、1リクエストの処理にかかった時間は4~72ミリ秒(ms)でその平均は11.054ミリ秒、転送レートは毎秒98479.32KBであることが分かる。

また、Webサーバーのスループットは同時接続数が増えるほど低下するのが一般的だ。たとえば次の例のように同時接続数を100に増やした場合、1リクエストの処理にかかった時間は平均121.709ミリ秒に増加しており、スループットは毎秒89439.06KBに低下していることが分かる。

$ ab -c 100 -n 10000 http://localhost/
This is ApacheBench, Version 2.3 <$Revision: 1706008 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (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
Completed 10000 requests
Finished 10000 requests


Server Software:        Apache/1.3.42
Server Hostname:        localhost
Server Port:            80

Document Path:          /
Document Length:        111114 bytes

Concurrency Level:      100
Time taken for tests:   12.171 seconds
Complete requests:      10000
Failed requests:        0
Total transferred:      1114674883 bytes
HTML transferred:       1111140000 bytes
Requests per second:    821.64 [#/sec] (mean)
Time per request:       121.709 [ms] (mean)
Time per request:       1.217 [ms] (mean, across all concurrent requests)
Transfer rate:          89439.06 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.5      0       7
Processing:     5  121  25.3    114     287
Waiting:        3  118  25.2    110     283
Total:         12  121  25.1    114     287

Percentage of the requests served within a certain time (ms)
  50%    114
  66%    128
  75%    138
  80%    143
  90%    156
  95%    166
  98%    180
  99%    193
 100%    287 (longest request)

なお、これはApache Benchに限らない話ではあるが、こういったベンチマークツールはそのツールを実行しているマシンの性能や、ツールを実行しているマシンとベンチマーク対象との間のネットワーク環境によって結果が変わってくる。そのため、サーバーソフトウェアが稼動しているマシン上で実行するだけでなく、同じネットワーク内の別のマシン上で実行したり、インターネット経由で実行したりと、環境を変えて試すことをおすすめする。

たとえば次の例は、インターネット経由で先ほどと同じサーバーに対してベンチマークテストを行ったものだ。この場合、1リクエスト辺りの平均処理時間は1009.492ミリ秒で、スループットは毎秒10783.08KB(約86Mbps)と大きく低下している。これは、テストで発生したトラフィックが使用したサーバーのインターネット接続回線帯域幅上限である100Mbps(「さくらの専用サーバ」標準の100Mbpsベストエフォート回線)に近づいたためと思われる。

$ ab -c 100 -n 10000 http://example.com/
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking example.com (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
Completed 10000 requests
Finished 10000 requests


Server Software:        Apache/1.3.42
Server Hostname:        example.com
Server Port:            80

Document Path:          /
Document Length:        111114 bytes

Concurrency Level:      100
Time taken for tests:   100.949 seconds
Complete requests:      10000
Failed requests:        0
Write errors:           0
Total transferred:      1114667835 bytes
HTML transferred:       1111140000 bytes
Requests per second:    99.06 [#/sec] (mean)
Time per request:       1009.492 [ms] (mean)
Time per request:       10.095 [ms] (mean, across all concurrent requests)
Transfer rate:          10783.08 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       26   79 155.2     56    3086
Processing:   137  922 156.1    889    2359
Waiting:       52  502 154.0    481    2108
Total:        166 1002 216.3    947    4105

Percentage of the requests served within a certain time (ms)
  50%    947
  66%    982
  75%   1014
  80%   1042
  90%   1151
  95%   1348
  98%   1906
  99%   1995

1Gbpsのローカルネットワークで接続されている別のマシンからベンチマークを実行した場合は次のようにスループットが毎秒82679.93KB(約661Mbps)となっていることから、上記のケースではネットワーク帯域がボトルネックになっていることが分かる。なお、ここではローカルネットワーク経由で接続を行わせるためIPアドレスで対象サーバーを指定し、送信するHTTPヘッダを追加する「-H」オプション(後述)で「Host:」ヘッダーを送信するよう指定している。

$ ab -c 100 -n 10000 -H "Host: example.com" http://192.168.1.100/
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
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.100 (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
Completed 10000 requests
Finished 10000 requests


Server Software:        Apache/1.3.42
Server Hostname:        192.168.1.100
Server Port:            80

Document Path:          /
Document Length:        111114 bytes

Concurrency Level:      100
Time taken for tests:   13.166 seconds
Complete requests:      10000
Failed requests:        0
Write errors:           0
Total transferred:      1114671913 bytes
HTML transferred:       1111140000 bytes
Requests per second:    759.54 [#/sec] (mean)
Time per request:       131.658 [ms] (mean)
Time per request:       1.317 [ms] (mean, across all concurrent requests)
Transfer rate:          82679.93 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1  10.1      1    1004
Processing:    10  129  37.3    125     743
Waiting:        7  115  31.6    110     739
Total:         11  130  38.3    126    1085

Percentage of the requests served within a certain time (ms)
  50%    126
  66%    138
  75%    146
  80%    152
  90%    164
  95%    174
  98%    215
  99%    312
 100%   1085 (longest request)

Apache Benchの主要オプション

テストサーバーや一般には公開していないサーバーなどの場合、Basic認証などのアクセス制限を設定している場合がある。こういったアクセス制限がかけられているサーバーやURLに対するテストを行う場合は、abコマンドのコマンドラインオプションで認証用のIDを指定してやれば良い。

たとえばBasic認証での認証が必要なサーバーの場合、次のように「-A」オプションで認証情報を指定できる。

-A <ユーザー名>:<パスワード>

また、「-H」オプションで送信するHTTPヘッダを追加できる。たとえば「Host: example.com」というHTTPヘッダを送信したい場合、次のように指定する。

-H "Host: example.com"

Cookieを使ってログイン情報を保持しているような場合は、Cookie情報を送信するようコマンドラインオプションで指定する。送信するCookie情報は、ログインした状態でWebブラウザでそのサイトにアクセスし、開発者用ツールなどで確認する。たとえばGoogle Chromeの場合、「デベロッパーツール」の「Network」タブでホストに送信しているHTTPヘッダを表示できるので、そこで「Cookie:」ヘッダの情報を確認する(図2)。

図2 Google Chromeではデベロッパーツールを利用することで送信しているCookieを確認できる

図2 Google Chromeではデベロッパーツールを利用することで送信しているCookieを確認できる

この例の場合、ホストには複数のCookieが送信されていたが、ログインに必要なのは「user=27448::kQp18UjdStmPdplkFadpVs」というCookieだ。この情報を「-C」オプションで指定する。-Cオプションでは、引数として「<キー>:<値>」という形でCookieの値を指定する。この例の場合は次のように指定する。

 -C user:27448::kQp18UjdStmPdplkFadpVs

もしくは、-Hオプションを使って「Cookie:」ヘッダを追加しても同様の結果が得られる。

-H "Cookie: user=27448::kQp18UjdStmPdplkFadpVs;"

複数のURLを対象に負荷テストを行える「Siege」

続いて紹介するのは、「Siege」という負荷テストツールだ。こちらもコマンドラインで操作するツールで、オープンソースソフトウェアとして提供されている。ライセンスはGPLv3だ。

SiegeはApache Benchと同様、指定したURLに対して連続してアクセスし、その結果を集計して表示するツールだが、特徴として「複数のURLを指定してそれぞれに順番にアクセスする」といったテストを実行できる点がある。また「指定した複数のURLからランダムにURLを選んでアクセスする」というテストも行える。これによって、サーバーに対し実際の運用環境に近い負荷をかけることができる。

SiegeはDebianやUbuntuでは公式パッケージとして提供されており、apt-getコマンド等でインストールできる。

# apt-get install siege

また、Red Hat Enterprise Linux 7やCentOS 7では拡張パッケージ集であるEPELリポジトリでsiegeパッケージが提供されており、こちらのリポジトリを利用してインストールが可能だ。

Siegeの基本的な使い方

Siegeではさまざまな方法でテスト対象となるURLを指定できる。もっともシンプルなのは、siegeコマンドの引数としてURLを指定する方法だ。たとえば「http://example.com/」というURLに対しテストを行うには、以下のようにする。

$ siege http://example.com/
** SIEGE 3.0.8
** Preparing 15 concurrent users for battle.
The server is now under siege...^C ←Ctrl+Cキーを押下する
Lifting the server siege...      done.

Transactions:                    179 hits
Availability:                 100.00 %
Elapsed time:                   6.79 secs
Data transferred:               5.48 MB
Response time:                  0.07 secs
Transaction rate:              26.36 trans/sec
Throughput:                     0.81 MB/sec
Concurrency:                    1.78
Successful transactions:         179
Failed transactions:               0
Longest transaction:            0.29
Shortest transaction:           0.01

FILE: /var/log/siege.log
You can disable this annoying message by editing
the .siegerc file in your home directory; change
the directive 'show-logfile' to false.
[error] unable to create log file: /var/log/siege.log: Permission denied

siegeコマンドのデフォルト設定ではテスト時間が設定されておらず、自動ではテストが終了されない。そのため、適当なタイミングでCtrl+Cキーを入力してテストを手動で終了させる必要がある。

テストを終了させると、それまでのリクエスト結果が出力される。この例では毎秒26.36個のリクエストを処理でき、その処理時間は0.01~0.29秒ということが分かる。なお、Siegeではログをファイルに出力する機能があるが、デフォルトではその保存先が一般ユーザーには書き込み権限が与えられていない「/var/log/siege.log」となっているためログの出力に失敗している。

上記の例では手動でテストを終了させていたが、テスト時間を指定してその時間が過ぎたら自動でテストを終了させることも可能だ。テスト時間は、「-t」オプションで指定できる。

-t <時間>[単位]

単位は「M」もしくは「m」(分)、「S」「s」(秒)、「H」「h」(時間)が指定可能だ。単位を指定しなかった場合、「m」が指定されたものとして扱われる。

また、siegeコマンドのデフォルト設定では同時接続数が15となっているが、これは「-c」オプションで変更できる。

-c <同時接続数>

複数のURLを対象にテストを行う

複数のURLを対象にテストを行うには、まずテストするURLを記述したテキストファイルを用意する。このファイルには次のように1行に1つずつのURLを記入する。

http://example.com/
http://example.com/story/16/01/16/0015218
http://example.com/story/15/12/28/035242
http://example.com/story/16/01/28/0437240/
http://example.com/~hylom/journal
http://example.com/journals
http://example.com/story/15/12/15/0646203
http://example.com/story/15/07/17/1855258
http://example.com/story/12/07/19/0814221

続いて、「-f」オプションでこのファイルを指定してsiegeコマンドを実行する。たとえば「urls.txt」というファイルにURLを記入した場合、以下のようになる。

$ siege -f urls.txt

この場合、指定したファイル中のURLに対し先頭から順にアクセスが行われる。先頭から末尾まですべてのURLにアクセスしたら、また先頭のURLに戻ってリクエストが続けられる。

POSTでのアクセスを行う

URLを指定する場合、「POST」というキーワードを付けることで、POSTリクエストを行うよう指定できる。また、送信するデータはGETリクエストにおけるクエリ文字列と同様の形で指定が可能だ。ここで指定したデータは「application/x-www-form-urlencoded」形式で送信される。

<URL> POST <キー1>=<値>&<キー2>=<値>&...

たとえば次のように指定することで、「http://example.com/login」というURLに対しPOSTでログイン情報を送信できる。もちろんサイトによって送信すべきパラメータは異なるので、実際に試す場合はそれに応じたデータを送信してほしい。

http://example.com/login POST userlogin=login&nickname=hylom&passwd=password

siegeコマンドでは「-g」オプションを指定することで、送受信されるHTTPヘッダを表示できる。これを利用し、テストを実行する前に指定したURLやPOSTデータが正しいかどうかを確認できる。

$ siege -g "http://example.com/login POST userlogin=login&nickname=hylom&passwd=password"
POST /login HTTP/1.0
Host: example.com
Accept: */*
User-Agent: Mozilla/5.0 (pc-x86_64-linux-gnu) Siege/3.0.8
Connection: close
Content-type: application/x-www-form-urlencoded
Content-length: 46

userlogin=login&nickname=hylom&passwd=password

HTTP/1.1 302 Found
Date: Tue, 13 Dec 2016 11:02:33 GMT
Location: /
Server: Mojolicious (Perl)
Connection: close
Set-Cookie: mojolicious=eyJleHBpcmVzIjoxNDgxNjMwNTUzLCJzZXNzaW9uIjp7InRva2VuIjoidXRXWVdYM2tPWkFxSjBOR2tsNzloR0FhRXdiUTBoQk9zN3ZNeEdVVk9KWUxFQ2ZuNW5zS3lMbHNCWVNtenBSdThBMFV0dVY4MVNwbVxuSmVRT1hJenNKQ2N1RTFHMUNxRlpkZDFuMHFhQSt6Nk9UTGtzMDJpY3Y0WWE3ZVp6OUR3azIvTG1kK3ZtSzFvbnM1SmFvUDFNbWZVN1xuZXo5cXhrK01ZVEZZNkRSYm1rdz1cbiIsInRpbWVzdGFtcCI6MTQ4MTYyNjk1MywicmVtb3RlX2FkZHIiOm51bGx9fQ----83bbb5e6df72f9f35ae1dd321cf5386c541ce5cf; expires=Tue, 13 Dec 2016 12:02:33 GMT; path=/; HttpOnly
Content-Length: 0
  
  

Siegeでのテスト例

Siegeでは指定したファイルに記載された先頭のURLから順にリクエストを発生させるので、これを利用して「サイトにログインしてあるアクセスを行いログアウトする」というようなユースケースを再現した負荷テストを行うことが可能だ。たとえば次の設定ファイルは、まずサイトにアクセスしたらログインし、ログインした状態で複数のURLにアクセスし、最後にログアウトする、という利用ケースを模したものだ。

http://example.com/  ←サイトのトップページにアクセス
http://example.com/login  ←ログインページにアクセス
http://example.com/login POST userlogin=login&nickname=hylom&passwd=passwd  ←ログイン
http://example.com/story/16/01/16/0015218
  以下、適当なアクセス
  
  
http://example.com/logout  ←ログアウト

また、-fオプションでアクセスするURLが記載されたテキストファイルを指定した場合、これに加えて「-i」オプションを指定することで、テキストファイルに記載されたURLをランダムに選んでアクセスするようなテストパターンを実行できる。これによって、実環境により近いようなアクセスパターンで負荷テストを実行することもできる。

認証が必要なサイトやページを対象にテストを行う

Siegeでは設定ファイルを用意することで、より詳しくその挙動をカスタマイズできる。設定ファイルはsiegeコマンドとともにインストールされる「siege.config」コマンドを実行することで作成できる。

$ siege.config
New configuration template added to /home/hylom/.siegerc
Run siege -C to view the current settings in that file

このコマンドを実行すると、ユーザーのホームディレクトリに「.siegerc」という設定ファイルが作成されるので、このファイルをテキストエディタなどで編集する。設定ファイル中には多数の設定項目が用意されているが、たとえばBasic認証で使用するユーザー名やパスワードの設定は「login」というパラメータで指定できる。

login = <ユーザー名>:<パスワード>
login = <ユーザー名>:<パスワード>:<realm>

この設定は複数の記入が可能だ。また、「realm」では、Basic認証が必要なページにアクセスした際にサーバーから送られるrealm文字列を指定する。サーバーから送られたrealm文字列がここで指定した文字列と一致した場合に、指定したユーザー名およびパスワードで認証が行われるようになる。realmを省略した場合はすべてのBasic認証が対象となる。

また、「login-url」パラメータではテストの実行前にアクセするURLを指定できる。

login-url = <URL>

このパラメータが指定されていた場合、Siegeはテストの実行時にまずこのURLにアクセスしてから他のURLにアクセスを行うようになる。通常、このURLにはログインを行うためのURLなどを指定することになる。ログインにPOSTアクセスが必要な場合は、前述の「POST」キーワードを使って次の例のようにURLを指定する。

login-url = http://example.com/login POST userlogin=login&nickname=hylom&passwd=passwd

そのほか設定ファイルではログの保存先や同時接続数、「keep-alive」接続を利用するかどうか、使用するプロクシなどさまざまな設定が可能だ。siege.configファイルで生成した設定ファイルではファイル中に各設定項目とその説明がコメントとして含まれているので、詳しくはそれらを参照して欲しい。

テストツールはネットワーク環境や用法を守って正しく利用しよう

Apache BenchやSiegeでは、コマンドラインで手軽に大量のアクセスを発生させることができる手軽さが便利なツールだ。そのため、単にWebサーバーの性能が要件を満たしているかを確認する以外に、チューニングやハードウェア構成の変更といった作業の効果を確認するためにも利用できる。サービス運用開始後にトラフィックに耐えられなくなるといったトラブルを回避するためにも、こういったツールを活用してサービスの性能を確認しておくと良いだろう。

なお、Apache BenchやSiegeに限らないが、こういった負荷テストツールは使い方を間違えたり、悪用したりするとサーバーに過大な負荷を与えることも可能で、それによって最悪サーバーやネットワークをダウンさせてしまう可能性もある。そのため、実運用されているサーバーや、第三者のサーバーなどに対しては不用意に実行しないよう注意したい。また、ホスティングサービスやクラウドなど第三者が管理しているインフラを利用している場合、負荷テストが攻撃だと誤認識される可能性もある点にも気を付けたい。

後編へ続く >