ブロードバンドタワー國武です。
負荷試験を行うには色々なツールがあります。
- apache bench
- JMeter
- httperf
- etc…
あるシステムの負荷試験に Erlang で実装されたマルチプロトコル対応の tsung というツールを使ってみたので、そのご紹介です。
tsungとは
tsung (以前は IDX-Tsunamiという名前でした)は様々なプロトコルに対応した erlang で書かれた負荷テストツールです。ライセンスはGNU GPL v2.0 として公開されています。1台、または複数台から、大量のユーザからのアクセスを模擬して負荷を掛けることができます。また、tsung はテスト結果をグラフとしてプロットすることも可能です。最新版の tsung では
- http/https
- WebDAV
- SOAP
- PostgreSQL
- MySQL
- LDAP
- Jabber/XMPP
- BOSH
- MQTT (MQTT v3.1)
- AMQP
などに対応していますが、ここでは http/https での測定を例に挙げます。
検証構成について
今回は
- myserver
- テスト対象のウェブサーバ
- tsung1
- 負荷テストツールの tsung のマスターサーバ兼スレーブサーバ
- tsung2
- 負荷テストツールのスレーブサーバ
として説明していきます。この記事では、tsung コマンドを実行するサーバをマスターサーバ、実際に負荷を掛けるテスターをスレーブサーバと呼ぶことにします。
インストール方法
実際にCentOS7 に tsung を導入してみます。tsung は、EPELリポジトリにパッケージがあります。tsung1, tsung2 それぞれにインストールしましょう。
$ sudo yum -y install epel-release $ sudo yum -y install tsung
また、グラフ化するために gnuplot や Perl の Template Toolkit を利用するので、それもインストールしておきます。
$ sudo yum -y install gnuplot perl-Template-Toolkit
設定方法
tsung の設定ファイルは XML で記述されます。tsung をインストールすると設定ファイルのサンプルが
- /usr/share/doc/tsung-1.5.1/examples
にインストールされるので、これを少しづつ書き換えながら使うのが一番簡単だと思います。今回は
- http_simple.xml
をベースに説明していきますが、tsung のマニュアルは非常に良く出来ていていますので、英語に抵抗のない方は、そちらを参照されたほうが間違いがないので、お勧めです。
まず手始めに自身のホームディレクトリに設定ファイルをコピーしておきます。
$ cp /usr/share/doc/tsung-1.5.1/examples/http_simple.xml ~/
http_simple.xml の初期内容は下記の通りです。
<?xml version="1.0"?> <!DOCTYPE tsung SYSTEM "@prefix@/share/@PACKAGE_NAME@/@DTD@"> <tsung loglevel="notice" version="1.0"> <!-- Client side setup --> <clients> <client host="localhost" use_controller_vm="true"/> </clients> <!-- Server side setup --> <servers> <server host="myserver" port="80" type="tcp"></server> </servers> <!-- to start os monitoring (cpu, network, memory). Use an erlang agent on the remote machine or SNMP. erlang is the default --> <monitoring> <monitor host="myserver" type="snmp"></monitor> </monitoring> <load> <!-- several arrival phases can be set: for each phase, you can set the mean inter-arrival time between new clients and the phase duration --> <arrivalphase phase="1" duration="10" unit="minute"> <users interarrival="2" unit="second"></users> </arrivalphase> </load> <options> <option type="ts_http" name="user_agent"> <user_agent probability="80">Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.8) Gecko/20050513 Galeon/1.3.21</user_agent> <user_agent probability="20">Mozilla/5.0 (Windows; U; Windows NT 5.2; fr-FR; rv:1.7.8) Gecko/20050511 Firefox/1.0.4</user_agent> </option> </options> <!-- start a session for a http user. the probability is the frequency of this type os session. The sum of all session's probabilities must be 100 --> <sessions> <session name="http-example" probability="100" type="ts_http"> <!-- full url with server name, this overrides the "server" config value --> <request> <http url="/" method="GET" version="1.1"></http> </request> <request> <http url="/images/accueil1.gif" method="GET" version="1.1" if_modified_since="Fri, 14 Nov 2003 02:43:31 GMT"></http> </request> <request> <http url="/images/accueil2.gif" method="GET" version="1.1" if_modified_since="Fri, 14 Nov 2003 02:43:31 GMT"></http> </request> <request> <http url="/images/accueil3.gif" method="GET" version="1.1" if_modified_since="Fri, 14 Nov 2003 02:43:31 GMT"></http> </request> <thinktime value="20" random="true"></thinktime> <request> <http url="/index.en.html" method="GET" version="1.1" ></http> </request> </session> </sessions> </tsung>
これを検証構成に合わせて書き換えていきます。なお、設定ファイル内ではホスト名で記載していますので、myserver, tsung1, tsung2 と、それぞれのIPアドレスを、事前に tsung1, tsung2 の /etc/hosts に書いておく必要があります。
tsung は ssh でスレーブサーバにログインして負荷テストを実行しているので、tsungのマスターサーバから各スレーブサーバに ssh でパスワード認証なしでログインできる必要があります。パスフレーズなしで ssh の鍵を作成してください(どうしてもパスフレーズなしでの運用が難しい場合には ssh-agent を利用しましょう)その後 tsung1 上で
$ ssh-copy-id tsung1 $ ssh-copy-id tsung2
を実行し、tsung1 から各サーバに ssh でログインできることを確認しておきます。
クライアント設定
まずはクライアント設定です。
<!-- Client side setup --> <clients> <client host="localhost" use_controller_vm="true"/> </clients>
ここでは、tsung1, tsung2 の2台で負荷をかける想定です。
<clients> <client host="tsung1" maxusers='30000'/> <client host="tsung2" maxusers='30000'/> </clients>
また、maxusers は、通常1プロセスあたりに開けるソケット数に制限があるため、これをバイパスするために利用される設定項目です(ユーザ数がmaxusersに達すると、use_controller_vm が true でない限り、新しい Erlang beam が立ち上がることで、この制限を回避します)。default値は800になっています。1プロセスあたりに開くことのできるファイル数(open files)は ulimit -n で確認できます。
$ ulimit -n 1024
制限を受けないようにするためには、maxusers の値はこの値よりも小さい値である必要があります。maxusers の値を大きくする場合には、事前に open files の値と TCP のチューニングを行っておきます。
- /etc/sysctl.conf
net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_tw_recycle = 1 net.ipv4.ip_local_port_range = 1024 65000 fs.file-max = 65000
内容を反映させるために、
$ sudo sysctl -p
を実行しておきましょう。
- /etc/security/limits.conf
* soft nofile 65000 * hard nofile 65000
limits.conf は、pam_limits から呼び出されているので、反映させるにはログインし直します。
サーバ設定
<servers> <server host="myserver" port="80" type="tcp"></server> </servers>
ここで myserver とあるのは、負荷を掛ける対象となるWebサーバ名です。ここでは http でのアクセス例ですが、https の場合には
<servers> <server host="myserver" port="443" type="ssl"></server> </servers>
とします。また、”servers” とあるように、複数台を対象とすることも可能ですが、ここでは単体でのテストとします。
モニター設定
<monitoring> <monitor host="myserver" type="snmp"></monitor> </monitoring>
モニター設定を入れることで、CPUやload avg、メモリ使用量などを測定できるとありますが、今回は削除しておきます。
負荷設定
次にどんな負荷を掛けるかを記述していきます。
<load> <!-- several arrival phases can be set: for each phase, you can set the mean inter-arrival time between new clients and the phase duration --> <arrivalphase phase="1" duration="10" unit="minute"> <users interarrival="2" unit="second"></users> </arrivalphase> </load> <options> <option type="ts_http" name="user_agent"> <user_agent probability="80">Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.8) Gecko/20050513 Galeon/1.3.21</user_agent> <user_agent probability="20">Mozilla/5.0 (Windows; U; Windows NT 5.2; fr-FR; rv:1.7.8) Gecko/20050511 Firefox/1.0.4</user_agent> </option> </options>
複数のフェーズを設けて、最初は負荷を低めでアクセスさせるといったこともできます。ここでは duration で指定された時間(分)の間、interarrival 秒ごとに、新規にセッションをサーバに張りに行きます。このセッションがすべて処理された段階でテストは終了することになります。ここでは少し複雑な場合を模擬します。
<load> <arrivalphase phase="1" duration="3" unit="minute"> <users maxnumber="100" interarrival="1" unit="second"></users> </arrivalphase> <arrivalphase phase="2" duration="3" unit="minute"> <users maxnumber="200" interarrival="0.1" unit="second"></users> </arrivalphase> </load>
上記設定とすることで、最初の3分間は 1秒間に1ユーザづつ新規にアクセスしてきます。ただし、100ユーザに達したら打ち止めです。次のフェーズでは 1秒間に10ユーザづつ新規にアクセスしてきます。こちらは 200ユーザに達したら打ち止めです。
後述するセッションで、1ユーザがリクエストするファイルが9ファイルだとすると、単純計算でも
10 ✕ 9 = 90 request/sec
の負荷を捌けないと遅延していくことがわかります。なお、<option> で指定されているのは、ユーザクライアントの情報です。probability の値により、どれぐらいの割合でその情報が使われるかが決まります。そのため probability の値は、すべて足して 100になる必要があります。
セッションの設定
次に、1ユーザが生成するアクセス内容を記述します。
<sessions> <session name="http-example" probability="100" type="ts_http"> <request> <http url="/" method="GET" version="1.1"></http> </request> <request> <http url="/images/accueil1.gif" method="GET" version="1.1" if_modified_since="Fri, 14 Nov 2003 02:43:31 GMT"></http> </request> <request> <http url="/images/accueil2.gif" method="GET" version="1.1" if_modified_since="Fri, 14 Nov 2003 02:43:31 GMT"></http> </request> <request> <http url="/images/accueil3.gif" method="GET" version="1.1" if_modified_since="Fri, 14 Nov 2003 02:43:31 GMT"></http> </request> <thinktime value="20" random="true"></thinktime> <request> <http url="/index.en.html" method="GET" version="1.1" ></http> </request> </session> </sessions>
<sessions> とあるように、複数の <session> を定義することも可能です。また、最新版では Basic認証だけでなくDigest認証、OAuth 1.0 での認証も可能になったそうですが、ここでは触れません。
ページ遷移を模すために、<thinktime></thinktime> で待ち時間を挿入することもできます。単位は秒数です。randome=”true”とすると、value を平均値とする指数分布となる待ち時間が挿入されます。
今回は、単純に複数の画像ファイルが貼られているページを1枚閲覧するケースを試しましょう。
<sessions> <session name="http-example" probability="100" type="ts_http"> <request> <http url="/" method="GET" version="1.1"></http> </request> <request> <http url="/01.jpg" method="GET" version="1.1" if_modified_since="Fri, 14 Nov 2003 02:43:31 GMT"></http> </request> <request> <http url="/02.jpg" method="GET" version="1.1" if_modified_since="Fri, 14 Nov 2003 02:43:31 GMT"></http> </request> <request> <http url="/03.jpg" method="GET" version="1.1" if_modified_since="Fri, 14 Nov 2003 02:43:31 GMT"></http> </request> <request> <http url="/04.jpg" method="GET" version="1.1" if_modified_since="Fri, 14 Nov 2003 02:43:31 GMT"></http> </request> <request> <http url="/05.jpg" method="GET" version="1.1" if_modified_since="Fri, 14 Nov 2003 02:43:31 GMT"></http> </request> <request> <http url="/06.jpg" method="GET" version="1.1" if_modified_since="Fri, 14 Nov 2003 02:43:31 GMT"></http> </request> <request> <http url="/07.jpg" method="GET" version="1.1" if_modified_since="Fri, 14 Nov 2003 02:43:31 GMT"></http> </request> <request> <http url="/08.jpg" method="GET" version="1.1" if_modified_since="Fri, 14 Nov 2003 02:43:31 GMT"></http> </request> </session> </sessions>
いちいち手で書くのは面倒だと思いますが、tsung-recorder を使うと、プロキシサーバとなって、ページ遷移を記録してくれたりもします。
$ tsung-recorder start Starting Tsung recorder on port 8090 "Record file: /home/vagrant/.tsung/tsung_recorder20160307-0053.xml"
default では 8090 番ポートを Listen するので、ブラウザにプロキシの設定をしましょう。記録を終えるには
$ tsung-recorder stop [OK]
とします。生成されたファイル(この例では ~/.tsung/tsung_recorder20160307-0053.xml) を眺めてみると
<session name='rec20160307-0055' probability='100' type='ts_http'> <request><http url='http://192.0.2.41/' version='1.1' method='GET'></http></request> <request><http url='/' version='1.1' method='GET'></http></request> <thinktime random='true' value='5'/> <request><http url='/' version='1.1' method='GET'></http></request> <thinktime random='true' value='7'/> <request><http url='http://192.0.2.40/' version='1.1' method='GET'></http></request> <request><http url='/01.jpg' version='1.1' method='GET'></http></request> <request><http url='/02.jpg' version='1.1' method='GET'></http></request> <request><http url='/03.jpg' version='1.1' method='GET'></http></request> <request><http url='/04.jpg' version='1.1' method='GET'></http></request> <request><http url='/05.jpg' version='1.1' method='GET'></http></request> <request><http url='/06.jpg' version='1.1' method='GET'></http></request> <request><http url='/07.jpg' version='1.1' method='GET'></http></request> <request><http url='/07.jpg' version='1.1' method='GET'></http></request> </session>
このように 〜 が生成されるので、利用する際には、設定ファイル内をこれで置き換えます。<http url=に、ブラウザでアクセスした際のホスト名が入るので、別途環境に合わせて修正する必要があることや、不要な<thinktime>の削除、意図せず外部サービスに負荷を掛けてしまわまいように、外部サービスを埋め込んでいる箇所(Facebookのいいねボタンや Google Analyticsのトラッキングコード)へのアクセスを削除するなど、微調整は別途必要になります。
上記の例では、最初誤って別サーバ(192.0.2.41)にアクセスした記録が残っているので、これも削除対象ですね。
実行する
実行ログを保存するためのディレクトリを作成しておきます。
$ sudo mkdir logs
あとは
$ tsung -l logs -f http_simple.xml start Starting Tsung "Log directory is: /home/vagrant/log/20160308-0730"
で実行されます。実行結果をグラフ化するには tsung_stats コマンドを実行します。html 形式でレポートが出力されます。実行したディレクトリにレポートファイルが出力されるので、適当なディレクトリを作成しておきましょう。
$ mkdir report && cd report $ tsung_stats --stats ../logs/20160308-0730/tsung.log
report.html を開くと
このように、テスト結果が表示されます。左ペインの Graphs Report をクリックするか、graph.html を直接開くと
のように、結果がグラフとして表示されます。tsung の設定ファイルはちょこちょこと書き換えて複数回テストすることになるかと思いますが、logs ディレクトリにその設定ファイルが保存されるので、どういった条件でテストしたかは、保存された設定ファイルを参照することでも確認可能です。
以上、簡単ですが tsung のご紹介でした。tsung では、簡単に高負荷を掛けられるので、一度検証などでお試しください。
本ブログの情報につきましては、自社の検証に基づいた結果からの情報提供であり、
品質保証を目的としたものではございません。