Apache Bench、WAST、JMeterを使った負荷テストのポイント | A Day In The Boy's Life

A Day In The Boy's Life

とあるエンジニアのとある1日のつぶやき。

負荷テスト(または性能テスト)は、システムを作り上げる上で重要な要素を持つテストになります。

しかしながら、システムを構築する段階ではあまりこの負荷や、サーバー(またはその上でのアプリケーションやミドルウェア)の性能というものは気にしません。

開発メンバーはせいぜい数十人といったレベルが多く、システムの開発段階ではそれだけの人のアクセスがないため、実際の利用状況とはかなり異なった環境で「動いたからOK」という感じで流してしまいがちです。


ただ、こういうことを気にせずにシステムをリリースしてみたら、一定のデータ量に達したらアプリケーションが動かなくなったり、サーバーが応答しなくなったなんて事があったりします。
そういうことがないためにも、リリース後の負荷を想定したテストや、システム全体の性能を予めテストしておく必要があります。


負荷テスト用のツールで市販されているものは、確かにきめ細かい結果を出してくれるものが多いのですが、高価でなかなか手が出しにくいものです。
ここでは、Apache Bench、Microsoft Web Application Stress Tool(WAST)、JMeterというフリーのツールを使った負荷テストの方法で、中でも特にシステム全体の応答時間を探る方法を書いて見たいと思います。


なお、ここで書いているツールはサーバーに過度の負荷を与える事ができてしまう為、自分の責任の範疇にある領域でのみ使用し、他の人が管理しているサーバー等には使用しないようにしてください。



負荷テストのポイント


まずは、どのように負荷テストを実施していけばいいのかを考えてみたいと思います。
これには、大きく2つの視点でのテスト方法があります。


1. 現在の負荷から改善効果を探りたい


まず、負荷テストを実施してみたい背景に、現在のパフォーマンスがネックになっており、改善の必要性があるといったことが考えられます。
この場合、アプリケーションの性能を改善してみてリリースしようにも、どれ位の改善が行われたのかを事前に調べる必要があります。
プログラムのロジックやSQLを見直してみて、パフォーマンスが改善したはずだと思い込んでみても、アプリケーションはそれ単体で動くという事はあまりないので、全体性能を見てみたらそんなに改善してなかった、またはより悪くなってしまったという事も考えられます。

この場合は、現在の負荷の度合いが分かっているはずなので、それが負荷テストを実施するうえでの一つのキーになる値となります。


例えば、同時に100人がシステムにアクセスすると途端にパフォーマンスが低下するなどです。
このあたりは、日々のアクセスログを解析してみて、ピーク時にどれ位のアクセスがあるのかでその数値が割り出せるはずです。
あまり厳密でなくて良いと思います。大体の値を割り出す事で負荷テストを実施するうえでの指標を見つけ出す事が重要になりますので。



2. 現在のシステム構成でどの位の負荷に耐えられるのかを調べたい


今度は1.とは逆に負荷テストをしてみる為の指標がない場合です。
新しくシステムをリリースする場合、そのシステムの利用者数や1日の負荷のデータが存在しない場合があります。

とは言え、システムを構築する際や、システムを運営して行く上での要件からその指標を見出す事はできます。
例えば、このシステムは3年後には会員数10万人を目指すなどの目標があるはずです。
または、(今はほとんど言われなくなりましたが)8秒ルールといったシステム応答時間に関する指標もあるかと思います。


であれば、会員数が10万人(そこから日に何人ぐらいのアクセスがあるかを予測して)となった場合でも、8秒以内に応答できるかどうかを検証してみることができます。
また、それ以上の負荷をかけてみて、現システム構成では会員数が何人まで耐えられるのかの予測値を導く事もできると思います。
この場合は、負荷のレベルを徐々に上げていき、その際の応答時間や単位時間当たりの処理数の遷移を見てみることで判断する事ができます。



何れにせよ、負荷テストで大事なのは予測でもいいので指標を定めてみて、それを満たすか否かの検証を繰り返してみるのが大事です。
では、具体的なツールの利用方法に移りたいと思います。



Apache Benchの利用方法


Apache Benchは、Apacheに付属している負荷テスト用のコマンドで、簡易的なテストであればこのコマンドだけでも十分に行えます。
利用する場合には、まずabというコマンドが存在するかどうかを確認してください。


# which ab
/usr/bin/ab

abコマンドを使って、あるサーバーに一定の時間の間、負荷をかけたい場合は


# ab -c {同時に実行したいリクエスト数} -t {負荷テストの実行時間(秒)} {URL}

とします。
例えば


# ab -c 10 -t 60 http://192.168.0.100/index.html

とすると、192.168.0.100のサーバーに対して同時接続10(-cオプション)で、60秒間(-nオプション)負荷をかけ続けます。
この場合、合計での処理数(リクエスト数)というのは分かりません。
なぜなら、あくまで同時にリクエストを10投げるというだけで、60秒間で合計どれだけのリクエストを処理できるかは対象のサーバーの処理能力によって異なってきます。


合計のリクエストを指定して負荷テストをしたい場合は、下記のように実行します。


# ab -c 10 -n 100 http://192.168.0.100/index.html

※ -nオプションの後に合計のリクエスト数を指定する。


この場合、合計100リクエストになった段階でテストが完了します。
時間を指定して(-tオプションで)性能テストを行う場合、負荷のレベルが対象サーバーごとに異なってきますが、合計のリクエスト数を指定すればどのサーバーに対しても同一の負荷レベルで結果を見比べるという事が可能になります。



Apache Benchのレポートの見方


abコマンドを実行すると下記のような結果が出力されます。


# ab -c 10 -n 1000 192.168.0.100/

This is ApacheBench, Version 2.0.41-dev <$Revision: 1.121.2.12 $> apache-2.0
Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/

Copyright (c) 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.0.100 (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Finished 1000 requests

Server Software: Apache
Server Hostname: 192.168.0.100
Server Port: 80
Document Path: /
Document Length: 20457 bytes
Concurrency Level: 10
Time taken for tests: 1.791311 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 20725064 bytes
HTML transferred: 20482096 bytes
Requests per second: 558.25 [#/sec] (mean)
Time per request: 17.913 [ms] (mean)
Time per request: 1.791 [ms] (mean, across all concurrent requests)
Transfer rate: 11298.43 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 3 1.0 4 6
Processing: 9 13 1.0 13 18
Waiting: 1 4 0.8 4 6
Total: 9 17 0.4 17 19
Percentage of the requests served within a certain time (ms)
50% 17
66% 17
75% 17
80% 17
90% 17
95% 17
98% 18
99% 18
100% 19 (longest request)


サーバーの応答時間を見る前に、テストしたリクエストが全て正常に処理できたかどうかを見てみましょう。
それは、「Failed requests」の項目を見てみればわかります。
この値が0以外であれば、サーバー側で処理が出来ずにエラーとなってしまったリクエストがあることを意味します。
そうであった場合は、今回のテストよりさらに高い負荷をかけてテストする事に意味はなくなってしまいます。
一部の処理が正常に処理できず、エラーとなってしまっているので、応答時間も求めるべき数字ではなくなってしまうからです。


また、テストするURLが正しいかどうかもあわせて確認しておきましょう。
存在しないページに対してabコマンドを実行してみてもあたかも、テストが正常に完了したかのような結果がでてきます。(404 File Not Foundのページが結果として出てくるためです)
そのような場合は、下記のようにHTTPステータスコードが200以外のリクエストがどれだけあったのかを示す項目が表示されます。


Non-2xx responses: 100

上記の項目が表示されていない事を確認する必要があります。

そして、応答時間についてですが「Time per request」の項目からわかります。


Time per request: 17.913 [ms] (mean)
Time per request: 1.791 [ms] (mean, across all concurrent requests)

2つ表示されますが、上が1リクエストあたりの応答時間で、下(across all concurrent requests)がTime per request / 同時リクエスト数の値となります。

また、システムの全体性能を見たい場合は「Requests per second」を見ることで、1秒あたりのリクエスト処理数を見ることが可能です。


Requests per second: 558.25 [#/sec] (mean)

全体としてシステムパフォーマンスが改善されたかどうかであれば、ここを見てみるだけでも判断が可能です。
(大きくなればパフォーマンスが改善された、小さくなると悪くなった)


最後にですが、Apache Benchは単一リクエストに対してしかテストを実行できません
ですので、先ほどのテストでは実際にブラウザでindex.htmlへアクセスした場合と結果が大きく異なる可能性があります。

理由は、Apache Benchでは単純にindex.htmlへのリクエストしか行わず、その中に含まれる画像などのリクエストを処理してくれない為です。
Apache Benchで負荷テストをする場合は、単一機能を提供するプログラムに限定してチェックしてみるのが有効です。

ですので、「負荷テストのポイント」であげた「1. 現在の負荷から改善効果を探りたい」という事はApache Benchで対応できますが、「2. 現在のシステム構成でどの位の負荷に耐えられるのかを調べたい」については向かないツールだといえます。



Microsoft Web Application Stress Toolの利用方法


WASTの使い方については、以前に書いたエントリを参考にしてみてください。


負荷テストあれこれ-Microsoft Web Application Stress Tool-


WASTを使った場合は、ある程度複雑なシナリオでテストをする事が可能です。
また、HTMLファイルに含まれる画像やCSSなどのリクエストも処理してくれるので、より実際の負荷に近い形でテストをする事ができます。


WASTは負荷テストを実行した後、上部のReportsボタンからテストの実施結果を詳細に見ることが可能です。


WAST-レポート



Microsoft Web Application Stress Toolのレポートの見方


下記が、WASTを実行した際に出力されるレポートの例になります。


Overview
================================================================================
Report name: 2008/11/09 11:23:05
Run on: 2008/11/09 11:23:05
Run length: 00:03:00
Web Application Stress Tool Version:1.1.293.1
Number of test clients: 1
Number of hits: 45937
Requests per Second: 255.20
Socket Statistics
--------------------------------------------------------------------------------
Socket Connects: 45941
Total Bytes Sent (in KB): 17322.24
Bytes Sent Rate (in KB/s): 96.23
Total Bytes Recv (in KB): 75050.71
Bytes Recv Rate (in KB/s): 416.94
Socket Errors
--------------------------------------------------------------------------------
Connect: 0
Send: 0
Recv: 0
Timeouts: 0
RDS Results
--------------------------------------------------------------------------------
Successful Queries: 0

Script Settings
================================================================================
Server: 192.168.0.100
Number of threads: 5
Test length: 00:03:00
Warmup: 00:00:00
Cooldown: 00:00:00
Use Random Delay: No
Follow Redirects: Yes
Max Redirect Depth: 15

Clients used in test
================================================================================
localhost
Clients not used in test
================================================================================

Result Codes
Code Description Count 
================================================================================
200 OK 45937

Page Summary
Page Hits TTFB Avg TTLB Avg Auth Query
================================================================================
GET /index.html 1482 468.49 483.91 No No
GET /common/lib.js 1482 1.98 2.39 No No
GET /common/style.css 1482 1.84 2.19 No No
GET /img/header1.gif 1482 1.76 1.84 No No
GET /img/header2.gif 1482 1.88 1.96 No No


WASTの場合、上記レポートの一番最後に出力されているように各リクエストごとの応答時間の結果を見ることができます。

結果を見れば分かるように、Apache Benchとは違い、複数のリクエストを実行してテストを実施する事が可能です。


「TTFB Avg」がリクエストに対して何らかの応答があるまでの平均時間、「TTLB Avg」が応答が完了するまでの平均時間となるため、「TTLB Avg」を応答時間としてみておけばよいでしょう。
また、Apache Benchと同様に1秒あたりのリクエスト処理数(Requests per Second)を見ることも同じレポート画面から見ることができます。


簡単なシナリオであれば、そのシナリオに沿った負荷テストが実施できますので、実際に利用者が使った場合の負荷を調べる事ができますし、その流れからどのページがパフォーマンスが悪いかもよくわかります。
また、「負荷テストのポイント」であげた「2. 現在のシステム構成でどの位の負荷に耐えられるのかを調べたい」についても、一連のシナリオに沿って負荷のレベルを徐々に上げていき、応答時間や単位時間当たりのリクエスト処理数の推移を見ることで、そのシステム構成でのパフォーマンスの限界値を明らかにする事もできます。

ただ、WAST自体がかなり古い負荷ツールで、2000年以降に更新されていない事、SSLのページに対して負荷テストを実施できない事などの欠点があります。



Apache JMeterの利用方法


最後に、JMeterです。
これも、以前に書いたエントリを参考にしてみてください。


負荷テストあれこれ-JMeterの使い方-


負荷テストあれこれ-JMeter 負荷のかけ方、レポートの見方-


JMeterは使い方が少し難しいツールにはなりますが、多種多様な負荷テストを実行する事が可能です。
基本的な使い方の方は以前のエントリを参照していただくとして、ここではJMeterを使って応答時間を計測する方法を説明します。



Apache JMeterのレポートの見方


まず、JMeterで応答時間を計測するには「リスナー」から「統計レポート」を追加します。


Jmeter-スレッドグループ


統計レポートを追加した状態で、負荷をかけてみると応答時間とスループットがわかります。


Jmeter-統計レポート


応答時間には、平均値、中央値、最小値、最大値など様々な結果が出てきます。
スレッド数が大きい場合、テストの結果の中で本来の結果とは大きくずれた値が出てくることもあるため、私は中央値で応答時間を見るようにしています。


また、JMeterのスループットはApache BenchやWeb Application Stress Toolの1秒あたりの処理数とは少し異なります。
これは、JMeterで負荷テストをする際に実行するスレッドの間隔を定義できるためで、全ての処理をサーバーが正常に処理出来た場合、下記の結果と同一になります。


スループット = (スレッド数 × ループ回数)/ Ramp-Up期間


例えば、1スレッドあたり10HTTPリクエストを送信するシナリオをセットしていて、60スレッド、ループ回数1、Ramp-Up期間を60秒にしてテストすると、1秒間に10リクエストずつ実行されます。
つまり、JMeterのスループットはそれ以上の処理がサーバー側に送られないので、スループットもそれより良くなりません(※)。


※ タイマをセットしなかった場合、1秒あたりの実行リクエスト数以上のスループットが出ることがあります。
  これは、1スレッドの中で実行されるリクエストが偏っているからです。
  例えば、1秒間に10リクエストを送信するテストを行う場合、実行のタイミングが来たらJMeterは一気に10リクエストを

  送信しようとします。

  タイマを使えば、例えば100msごとに1リクエストを送信するなど、均等に処理を実行させる事ができます。


Apache BenchやWASTのように、1秒あたりにどの位の処理が出来るかを調べたい場合は、スレッドグループ画面の「ループ回数」の「無限ループ」にチェックを入れれば、絶え間なくリクエストを送信してくれます。


Jmeter-スレッドグループ


※ こうした場合、テストは自動で終了しないため、手動で終了させる必要が出てきます。

JMeterは非常に高機能で、複雑なシナリオに沿ったテストも実行できますが、テストするクライアントマシンの負荷もそれなりにかかる為、性能の良いものを用意するか、複数台でテストを実施するなどの工夫が必要です。
スループットがでないなぁとか思っていたら実はそれはクライアントマシンの性能が悪かった為ということも少なくありません。
クライアントマシン自体の負荷も見つつ、適度にこなせる処理数の負荷でテストを実行する必要があります。



3つのフリーの負荷ツールを紹介してみましたが、それぞれ出来る事も違っています。
簡易的にベンチマークをとりたいのであれば、Apache Benchでも十分でしょうし、より実際の状況に近い負荷をかけたい場合はJMeterが有効です。
用途に応じて、負荷テストのツールを使う事で効率的にテストを行えると思います。