負荷テスト

TsungによるwebSocketの負荷テスト (テスト設定ファイル編)

Tsungの環境構築ができたので 実際にテストのシナリオをxml形式で作成します。

tsung.xmlの作成

詳しい設定は公式リファレンスを参照

今回のテストで達成したかった内容は サーバ側アプリケーションのwebsocketのエンドポイントに対して

  • 一定のCCU(Concurrent Users)達成時の、サーバ側の振る舞い(処理ロジックと応答速度とサーバ負荷)の確認
  • DAU(Daily Active User)達成時の、サーバ側の振る舞い(処理ロジックと応答速度とサーバ負荷)の確認

の2点のため、Tsungがエミュレートするクライアント側の処理はできるだけシンプルにしました。

DAUについてはとにかく数を増やして完了したプロセスから終わっても問題ないのですが、 一定数のCCUを達成するにはwebsocketのコネクションを確立したTsungプロセスを活かして置く必要があります。 そのため、heartbeatメッセージのような処理をループで追加しないと Tsungが生成したユーザはセッション完了後にプロセスを終了するのでCCUが維持できません。

注意点としては

TsungではwebsocketPing/Pongはまだ扱えない?ため サーバ側でPingを送ってもそれを処理することはできません。

また、日本語などの2byte文字もダメっぽいです。

実際に作ったxmlのサンプル

複雑なxmlと変数

xml内でErlangのモジュールを読み込んで処理したり、scriptとしてevalさせるなんて事もできます。 またJMeterのようにcsvを読み込むことももちろん可能です。

http://tsung.erlang-projects.org/user_manual/conf-advanced-features.html#dynamic-substitutions

ただしErlangについての知識がないととっつきにくいのです。僕は諦めました。

<setdynvars sourcetype="eval" code="fun({Pid, DynVars}) ->
                    case random:uniform(3) of
                      1 -> " low";
                      2 ->  "mid";
                      3 -> "high";
                    end."
                  >
                  <var name="my_dynamic_var" />
              

こう書くと、my_dynamic_varという変数がセットできます。 これを

<if var="my_dynamic_var" eq="3">
              
              </if>
              

とか

<websocket frame="text" type="message">{"my_dynamic_var":%%_my_dynamic_var%%}</websocket>
              

と言った風に使うことができます。

レポートの出力

Tsung 実行時に ~/.tsung/log/XXXが作成され、そのディレクトリに各Tsungクライアントからログが集まってきます。

ログディレクトリに移動して以下のコマンドでhtml化されたグラフが生成されます。

~/opt/tsung-1.5.0/lib/tsung/bin/tsung_stats.pl

簡単でいいですね。

その他

今回はTsungに加えてNodeJSのwebsocket-benchも試してみました。 こちらはローカルマシンからもお手軽に実施でき、JavaScriptなのでwebSocketの処理も書きやすいです。

最終的に僕はTsungで一定数のCCUを達成した状態で、websocket-benchで細かい処理を書いたクライアントを走らせて応答処理時間を測るという方針でテストを実施しました。

TsungによるwebSocketの負荷テスト (環境構築編)

ここ最近仕事でTsungを使って負荷テストをした。

Tsungの日本語情報が全然見つからないのでせっかくなのでブログに残しておきます。

あくまでも個人的なメモのため、詳細は一次情報を参照してください。

0.Tsungとは

  • オープンソースのマルチプロトコル対応のerlang製分散負荷テストツール
  • 対応しているプロトコルは、HTTP(S)、WebSocketの他、WebDAV、SOAP、PostgreSQL、MySQL、LDAP、Jabber/XMPPなど
  • 数十万単位のユーザーをシュミレートできる
  • 設定はxmlで記述することができる
  • などなど...

今回Tsungを使用した理由は、

  • webSocketでDAUで100万ユーザーまで試す必要があったこと(JMeterはあまり調べていないが、Tsungは1.5.0以降でwebSocketをサポートしている)
  • 結果のグラフ出力が簡単
  • 社内にTsungに詳しい人材
  • などなど...

1.環境構築

1-1.各種参考資料

基本はNgocさんのスライドを読めば大体わかります。

1-2.インストール

詳細はtsart/amazonlinux.mdにメモしてあります。

今回はAWSのm1.largeインスタンスで、OSはAmazonLinuxを使用しました。

負荷テストのためだけに使うインスタンスなので全てのポートのTCP通信を許可しておきます。

OSのセットアップ

TsungのはErlangのプロセスを大量に作成するのでカーネルの設定を変更します。

/etc/security/limits.conf

/etc/sysctl.conf

ここらへんはxitrum-guideとほぼ内容は一緒。

Erlangのインストール

Tsungは大量のプロセス生成や、beamを使用したTsungサーバ間で分散処理などErlangの特徴が活かされているようです。

なにはともあれ、Erlang上で動くのでErlang OTPをダウンロードしてビルドします。

mkdir ~/opt
              
              sudo yum install ncurses-devel
              
              sudo yum install openssl-devel
              
              wget http://www.erlang.org/download/otp_src_R16B03-1.tar.gz
              
              tar xzf otp_src_R16B03-1.tar.gz
              
              cd otp_src_R16B03-1
              
              ./configure --prefix=$HOME/opt/erlang-R16B03-1
              
              make install
              
              sudo echo 'pathmunge /home/ec2-user/opt/erlang-R16B03-1/bin' > /etc/profile.d/erlang.sh
              
              sudo chmod +x /etc/profile.d/erlang.sh
              

Tsungのインストール

最新安定版は1.5.0ですが、 今回はwebSocketのframeタイプを指定できるようにしたかった(1.5.0ではbinaryモードのみ)のでgithubの最新ソースコードからビルドします。

sudo yum install git
              
              sudo yum install autoconf
              
              git clone https://github.com/processone/tsung.git tsung-latest
              
              cd tsung-latest/
              
              ./configure --prefix=$HOME/opt/tsung-latest
              
              make install
              

確認(Erlangのrepl開始)

erl
              

replの終了

q().
              

Tsungレポート出力用ツールのインストール

Tsungの結果のグラフ化はpythonで、html化はperlで行われるようなのでその準備をします。

sudo yum install numpy
              
              sudo yum install scipy
              
              sudo yum install python-matplotlib
              
              sudo yum install gnuplot
              
              sudo yum install perl-CPAN
              
              sudo cpan Template
              

SSHの設定

TsungはコントロールサーバとTsungクライアント間でSSHで通信しているようなので、 ホスト名のみでログインできるようにキーの設定をしておく必要があります。

今回はAWSなのでローカルマシンからAWSへのログインキーをそのままインスタンス上にコピーしました。

# ローカルから EC2へコピー
              scp -i XXXX.key XXXX.key ec2-user@host:/home/user/ec2-user/.ssh/
              
              # EC2上でリネームコピー
              mv ~/.ssh/XXXXX.key ~/.ssh/id.rsa
              # sshでログインできることを確認
              ssh localhost erl
              exit
              

1-3.試し実行

さて、これでとりあえず1台構成でTsungを動かす準備ができたので exampleにあるxmlをコピーして 少し修正したらTsungが動くか確認します。

xmlをコピーした際に注意すべき点は

  • DOCTYPE tsung SYSTEM のパスが正しく設定できているか。(今回は<!DOCTYPE tsung SYSTEM "/home/ec2-user/opt/tsung-latest/share/tsung/tsung-1.0.dtd">とします。)
  • clients > clientタグのhost属性が正しくさっきSSH設定したホスト名で設定できているか。(今回はlocalhost
  • servers > serverタグのhost属性が負荷テスト対象のホスト名になっているか。

テストの開始

~/opt/tsung-latest/bin/tsung -f sample.xml start
              

ステータスの確認

~/opt/tsung-latest/bin/tsung -f status
              

レポートの出力

cd ~/.tsung/log/XXX/
              ~/opt/tsung-1.5.0/lib/tsung/bin/tsung_stats.pl
              

その他

レポートをzip化

sudo yum install zip
              zip tsung_report.zip -r ~/.tsung/log/XXX
              

簡易HTTPサーバ起動

python -m SimpleHTTPServer
              

1-4.分散環境の構築

無事シングルノードでTsungの動作が確認できたら分散環境を構築します。

今回はEC2のAMIを作成してしまえばとても簡単ですが、

公式のFAQにもあるように sshの設定をちゃんとしてあげないとクライアントに繋がらなくなるので以下のようにします。

AMIからインスタンスを作成したら各サーバ間(今回はtsung1,tsung2,tsung3としました)で接続できるようにします。

インスタンスをコピーしているので認証キーは同じものなので、 etc/hostsに以下のように記述します。EC2インスタンス間はプライベートIPで通信するようにしておくことでお得らしいです。

127.0.0.1   localhost localhost.localdomain
              <tsung1_Private_IP> tsung1
              <tsung2_Private_IP> tsung2
              <tsung3_Private_IP> tsung3
              

各サーバで確認します。(tsung2,tsung3はtsung1を元にコピーしているので最初にtsung1のlocalhost設定を削除します。rm -rf ~/.ssh/knownhosts)

ssh tsung1 erl
              exit
              ssh tsung1 erl
              exit
              ssh tsung1 erl
              exit
              ssh localhost erl
              exit
              

また、Erlang上でも接続できるか確認します。

erl -rsh ssh -sname foo -setcookie mycookie
              Eshell V5.4.3 (abort with ^G)
              (foo@tsung1)1>slave:start(tsung2,bar,"-setcookie mycookie").
              {ok,bar@tsung2}
              

これで準備ができたので、次回は設定ファイルについて書きます。