1. ホーム
  2. Blog
  3. keep-aliveでHTTPコネクションを放置するベンチマーク(abパッチ)

keep-aliveでHTTPコネクションを放置するベンチマーク(abパッチ)

川崎 有亮

川崎 有亮

技術

川崎です。ab(Apacheのベンチマークツール)のパッチを書いてみました。
例えば、『KeepAlive On なウェブサーバの最大同時接続数制限が100本の環境で、
1,000台の PC から「いっせーの」でブラウザのボタンが押されて
ほぼ同時にアクセスが来ても大丈夫?』といった状態を再現できます。

KeepAlive は、画像ファイルなどのコンテンツのダウンロードを連続化する
ことで HTTP サーバの負荷を低減し、また、同時にブラウザの描画時間を
短くしてくれる効果があります。
しかし、用途によっては、弊害が出る場合もあります。

サーバ側のキープアライブのタイムアウト(KeepAliveTimeout)の設定が長い場合、
ページの描画が終わっているにも関わらず、HTTP コネクションがそのまま継続し、
結果的にゾンビ的なコネクションが残ってしまうことになります。

この状態での処理性能は、単純なベンチマークでは測定が難しいです。

ちなみに、Apache 2.0.x 系のデフォルトは、KeepAliveTimeout 15 秒でした。
Apache 2.2.9 では、KeepAliveTimeout 5 秒に短縮されています。
ブラウザ側(Firefox 2.0)network.http.keep-alive.timeout のデフォルトは、300秒です。

2.0 のデフォルト値で MaxClients 150、KeepAliveTimeout 15 とすると、
可能性として、150クライアントが15秒間繋ぎっ放しになる場合があります。
どんなに CPU が余っていても、ネットワーク回線が太くても、最悪の場合は
150リクエスト/15秒(=10リクエスト/秒)しか性能が出ません。

「KeepAlive の設定はちゃんと検討しょう」が基本ということになりますが、
キープアライブでこの『150クライアントが15秒間繋ぎっ放し』の状態を再現して
性能試験できるベンチマークツールが見当たらなかったので、作ってみました。
Apache のベンチマークツール ab へのパッチです。
http://recruit-mtl.googlecode.com/svn/trunk/misc/ab-keepconn/ab-keepconn.diff

パッチの適用手順は、以下の通りです。

wget http://recruit-mtl.googlecode.com/svn/trunk/misc/ab-keepconn/ab-keepconn.diff
wget http://ftp.kddilabs.jp/infosystems/apache/httpd/httpd-2.2.9.tar.bz2
bunzip2 < httpd-2.2.9.tar.bz2 | tar xvf -
cd httpd-2.2.9
./configure --prefix=/usr/local/httpd-2.2.9
cd srclib
make
cd ../support
patch < ../../ab-keepconn.diff
make
ここでは、最新の 2.2.9 を使っていますが、たぶん他のバージョンでも動くかと。

使い方は、『-K』オプションを付けて ab を実行すると、キープアライブで
コネクションを保ったままにして、それ以降、再利用せずに、放置します。

./ab -K -n 1000 -c 100 http://example.com/
最大100本同時接続で、合計1,000回のリクエストを投げます。
Connection: keep-alive は発行するものの、その HTTP コネクションは
1リクエストのみで利用します。サーバ側の最大同時接続数に達した場合
キープアライブがタイムアウトするまで、次のリクエストが送れず待ちます。

サーバ側の最大同時接続数が100本の環境で、1,000台の PC からほぼ同時に
アクセスが来ているような状態を再現しています。
人手で再現するのは、とてもコストがかかりますが、ツールなら一瞬。
 
ベンチマーク結果の表示は通常と同じです。
『Time per request』は最大同時接続数に達してるので、意味が薄い。
『Requests per second:』が単純な性能数値として分かりやすいです。
ある程度、試行回数 -n の値は多く設定した方が実際に近い値になります。

例えば「-K -n 1200 -c 300」の結果例です:

Concurrency Level: 300
Time taken for tests: 8.716 seconds
Complete requests: 1200
Failed requests: 0
Write errors: 0
Total transferred: 6646950 bytes
HTML transferred: 6241539 bytes
Requests per second: 137.68 [#/sec] (mean) ←『137req/秒の性能』
Time per request: 2178.941 [ms] (mean)
Time per request: 7.263 [ms] (mean, across all concurrent requests)
Transfer rate: 744.76 [Kbytes/sec] received

Percentage of the requests served within a certain time (ms)
50% 234
66% 277
75% 317
80% 332
90% 382
95% 429 ←『95%以上を0.5秒以内にリクエストを返した』
98% 3164 ←『キープアライブのタイムアウト待ちになった』
99% 3215
100% 3314 (longest request)

ちなみに、素の状態の ab でもキープアライブに対応していますが、
その -k オプションは「キープアライブで接続したコネクションで
そのまま続けてリクエストを投げた性能」を測るためのオプションで、
HTTP コネクションのゾンビ状態を再現しません。
今回は、「キープアライブで接続したコネクションはそのまま放置して
おいて、別のコネクションでリクエストを投げた性能」を測りたい。

また、JMeter は(デフォルトでは?)キープアライブに対応していない模様。

JMeter sets the Connection: keep-alive header. This does not work
properly with the default HTTP implementation, as connection re-use is
not under user-control.

PS)
かなり久しぶりに C のコードを書きました。
Jcode の FB_XMLCREF 相当パッチ を書いて以来かなあ。(3年ぶり?)

トップへ戻る