2014年11月13日木曜日

HTTP ベンチマークツール wrk の使い方

http://www.flickr.com/photos/dandechiaro/4151566643

https://github.com/wg/wrk.git
Will GlozerさんのHTTPベンチマークツール wrk をインストールして使ってみます。
曰く、Modern HTTP benchmarking toolだそうです。
HTTP/1.1対応のベンチマークツールで、負荷をかける時間を決めて試験することが出来ます。

Mac OS Xの場合。
$ brew search wrk
$ brew install wrk

CentOS6の場合。
事前にyumライブラリを用意してインストールします
# sudo yum groupinstall 'Development Tools'
# sudo yum install  openssl-devel
# sudo yum install  git
# git clone https://github.com/wg/wrk.git
# cd wrk
# make
# sudo cp wrk /usr/bin/wrk

バージョンを確認します。
# wrk --version
wrk 3.1.1 [epoll] Copyright (C) 2012 Will Glozer
Usage: wrk  
  Options:
    -c, --connections   Connections to keep open
    -d, --duration      Duration of test
    -t, --threads       Number of threads to use

    -s, --script        Load Lua script file
    -H, --header        Add header to request
        --latency          Print latency statistics
        --timeout       Socket/request timeout
    -v, --version          Print version details

  Numeric arguments may include a SI unit (1k, 1M, 1G)
  Time arguments may include a time unit (2s, 2m, 2h)

wrkを実行してみます。12スレッド起動し、合計400接続を30秒間リクエストを送信します。
$ wrk -t12 -c400 -d30s http://192.168.33.10/
Running 30s test @ http://192.168.33.10/
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    88.84ms  167.00ms 942.61ms   91.55%
    Req/Sec   705.81    459.71     3.70k    79.74%
  232063 requests in 30.00s, 187.88MB read
Requests/sec:   7735.40
Transfer/sec:      6.26MB

ベンチマークのヒントが書いてありましたので、簡単に訳してみました。
Benchmarking Tips

The machine running wrk must have a sufficient number of ephemeral ports
available and closed sockets should be recycled quickly. To handle the
initial connection burst the server's listen(2) backlog should be greater
than the number of concurrent connections being tested.

A user script that only changes the HTTP method, path, adds headers or
a body, will have no performance impact. If multiple HTTP requests are
necessary they should be pre-generated and returned via a quick lookup in
the request() call. Per-request actions, particularly building a new HTTP
request, and use of response() will necessarily reduce the amount of load
that can be generated.

wrkを走らせるマシンは十分なエフェメラルポートを持っている必要があり、閉じたソケットは迅速に再利用されるべきです。
初期接続を処理するために、サーバーのlisten(2) backlogのバーストが、テストされている同時接続数よりも大きくなければなりません。

ユーザスクリプトは、パフォーマンスに影響を与えないHTTPメソッド、パス、ヘッダーの追加もしくはbodyを変更できます。
もし、多数のHTTPリクエストが必要な場合は、それらは事前に生成された迅速な request() の呼び出しにより返されるはずです。
リクエストごとのアクション、新しいHTTPリクエストの生成とresponse() は、生み出される負荷の絶対量を減らすでしょう。


参考)

net.core.somaxconnについて調べてみた
http://d.hatena.ne.jp/tetsuyai/20111220/1324466655

Unicorn!
https://github.com/blog/517-unicorn
Unicornのbacklog設定についての説明がある。

listen()のbacklogが不足した際のTCP_DEFER_ACCEPTの動作について
http://blog.nomadscafe.jp/2014/05/listenbacklogtcp-defer-accept.html

nginx + PHP-FPM for high loaded websites
http://www.saltwaterc.eu/nginx-php-fpm-for-high-loaded-websites.html

EC2など 高負荷クラウド環境における Redis のチューニングについて
http://tech.guitarrapc.com/entry/2013/08/02/210858