2011年9月18日日曜日

FlazrをつかったJmeterのRtmpSamplerつくりました。

Flazrの記事は何度か書きましたが、Rtmp接続を実行し、サーバーとやりとりをするJavaプログラムです。

これを利用したRtmpSamplerをつくってみました。
いつものgithubのリポジトリです。
https://github.com/taktod/RtmpPluginForJmeterWithFlazr

いままでRed5のRtmpClientで作成していましたが、それでは対応できなかったFMSへの接続も可能になってます。
関数の呼び出しは、Flazrでは内部データになっていたのですが、それを独自に利用できるように改造しました。
内部データ的にFlazr 0.7 RC2を利用していますので、それ以外のバージョン(ソースも含む)だときちんと動作しないかもしれません。

いままでのRtmpClientの機能をとりあえず実現したのですが、それ以外にも次のようなことができそう。

  • swfファイルのバイナリ情報を元にサーバーに接続させる。
  • Flashバージョンを任意の番号にする。
  • 動画の録画動作をシミュレーションする。
  • SharedObjectのやりとりをシミュレーションする。
  • 実際にRtmpDumpみたいに録画する。
  • ローカルファイルをサーバーにPublishする。
このまま開発をすすめれば上記のようなことができるようになりそう。

フラッシュバージョンやアクセスパスを偽装できるので、RtmpDumpより協力な、ちょっとやばめなツールになりそうだね。

2011年9月17日土曜日

log4jでlog4j.propertiesを使わない方法

apache.log4jの解説ページをみているとlog4j.propertiesを読み込むこと必須になっているものばかりなので、このファイルなしで動作させる方法を調べてみた。


Logger logger = Logger.getRootLogger();
logger.setLevel(Level.INFO);
logger.addAppender(new ConsoleAppender(new SimpleLayout()));

これをLogger呼び出しを行う前に実行しておけば万事OK。

RtmpClientの使い方その6、Flazrをつかってみる。

Flazrの記事なのでRtmpClientではないです。
Flazr(http://flazr.com/)というのは、sourceForgeで開発されているJBossベースのRtmpサーバー、クライアント実装。
Red5がサーバーよりだとすれば、このプロジェクトはクライアントよりです。

5月下旬あたりに書いたRtmpClientに関する記事を見てもらえばわかりますが(これとか)、Red5のRtmpClientはいくつか動作がおかしいところがあるらしく、FlashMediaServerに接続できませんが、Flazrでは問題なく接続できて、映像データを取得したりできます。

なので、RtmpのJmeterの実装をFlazrベースに書き換えるのを目標にちょっとFlazrを勉強してみようかと思います。

いまのところわかっているFlazrのデータについて
・必要ライブラリをひっくるめて2MB以下
・動作はいたってシンプル。
・動画ファイルをストリーム変換して放送したり、サーバーから視聴しつつ動画ファイルにするといったこともサポート
・SharedObjectはサポート外(命令の定義はあるけど動作プログラムは抜けている?)
・サーバー側関数呼び出し定義や、クライアント側関数呼び出し定義の実装もどうやらなさそう(プログラムはあるけど、起動オプションで利用する方法がないっぽい。)
・パケットの扱いはRed5とは別になっているので、Red5との連携やXuggleに流してエンコードしたりということはやりにくそう。
・Red5のRtmpClientはehcacheを経由してデータのやりとりをしているので、PC内にcacheアクセスが必要になるが、Flazrではそれはない。
・標準で接続→視聴動作の負荷テスト(インスタンスを大量につくって同時に視聴状態をつくる)というのがある。

とりあえずは、EclipseでJavaアプリ書いてRed5に接続するところからやってみるかな。

2011年9月15日木曜日

Jmeterの使い方、サンプラーのデータを次のサンプラーに使い回す。

昨日の記事で予告した、サンプラーの結果を次の動作につなげる機能・・・

記事にしたいと思います。
目標は
「2chの板一覧にアクセスして、そこから[なんとか.2ch.net/なんとか]のアドレスを抽出して、次のアクセスに利用する。」

まず、おなじみJmeterでHttpアクセスをつくってみる。
リクエストその2は、とりあえず必要ないので、無効化
Httpリクエストのところにhttp://menu.2ch.net/bbstable.html
を準備する。
そして実行、「結果をツリーで表示」の結果を確認
ここで左下のTextとなっているタブの情報を「RegExp Tester」に変えます。
正規表現テストをすることができる便利機能です。
Htmlのソースとともに、テスト用のボックスとテストボタンができているので正規表現を設置しテストしてみます。
今回は「なんとか.2ch.net/なんとか」を抽出したいので、
http://([a-z]+).2ch.net([/a-z]+)
こんな正規表現にしました。
では、正規表現を2つ追加します。1つは、xxx.2ch.netのサーバーアドレスを作成する用。
もう1つは板のアドレス用です。
サーバーの指定は
参照名server
正規表現は先ほどつくったやつ。
テンプレートはどのような値を変数にいれるかの指定です。
今回は[1つめにマッチしたもの].2ch.netという形をつくるので
[$1$.2ch.net]を指定
一致番号は、正規表現で一致した何番目のデータを利用するかというもの。
今回は適当に5にしました。
 続いて板のアドレス側の設定
参照名をbbsにしました。
1つの検索の何番目の一致を利用するかは、$n$という形で指定します。
いくつめの検索を利用するかは、一致番号で指定します。(一致番号を入力しないとランダムに選択されます。)

参照データはできあがったので、今度はこの参照データを利用してリクエストその2を構築します。
内容はこんな感じ${変数名}で代入させることができます。
では、さっそく実行
2回目のリクエストの結果として、地震速報の板が取得できました。(結果表示はHTMLを選択してあります。)

これで結果から正規表現でデータを抜き出して、それを利用して次のサンプラーを実行する・・・という操作ができました。

2011年9月14日水曜日

Jmeterの使い方、JDBCについて

前回のJmeterについての記事では、簡単にHttpで接続して反応をみていました。

今回はJDBCを使う方法について記事を書きます。
JDBCをつかった動作の有名どころはMySQLあたりなのですが、会社の環境ならともかく、家の環境でちょちょいとMySQLサーバーをセットアップするのは面倒だったので、今回はSqlite3をつかったJDBC接続をためしてみたいと思います。
基本的なことはほかのと同じなので、MySQLやPostgreSQLなどで動作検証したい方の参考にもなると思います。

まず必要なものを準備します。JDBCで接続するためには、接続するのに利用するConnectorのライブラリをダウンロードする必要があります。

今回ぼくはSqlite3を利用するにあたって、XerialのSQLiteJDBCを利用しました。
対象サイトにいき、sqlite-JDBC-3.7.2.jarを入手しました。
サイトのここのhereのリンクからたどって
 sqlite-jdbc-3.7.2.jarを入手

入手したライブラリはjmeterのディレクトリのlib/extの中に設置しました。

今回はsqlite3を利用して、insertとselectの動作をためしてみようと思います。
とりあえずcreate table test(id integer, name varchar(16));
を実行して、あらかじめデータを扱うためのデータベースファイルとテーブルを作成しておきました。
作成するときにこちらのサイトを参考にしました。

ここまでできたらJmeterの設定をすすめます。
今回必要になるものはJDBC Connection ConfigurationとJDBC Requestのこの2つです。
こんなテスト計画を作成してみました。
やることはSelect * from test;の全件検索を2回とInsert into test values(4, "myself");
(入力データはなんでもいいのですが)の挿入を1回を試行するだけです。

各要素の中身はJDBC Connection Configuration
jdbcの設定の部分 jdbc:sqlite:適当なDBファイルのアドレス
Driver classはXerialのサイトのSample.javaの記述からorg.sqlite.JDBCなのでそれを登録。

あとはVariableNameに適当な名前(今回はsqlite)を追加する。
これが入力すべき事項です。

続いてJDBC Requestのサンプラーの部分
VariableNameに先ほどのsqliteをいれること。
Queryの種類にあわせてQueryTypeを変えておくことこの2点だけ注意です。
Insertの例
 Selectの例

あとは、サンプリングの結果用のビューを適当につけます。今回はとりあえず「結果をツリーで表示」をセット。

試行回数を1回1ループにして実行
結果はこんな感じになります。
もともといれてあった3つの要素に、mysqlが4番として追加されました。

さて、これでMySQLだろうがSqliteだろうがProgreSQLだろうが、JDBCのドライバさえ入手してしまえば、Jmeterで負荷テストができるようになったわけです。

次は、Jmeterで呼び出した結果を取得して、それを次のサンプリングのときにパラメーターとして使う方法でも書こうかな。
パラメーターがつかえるようになると、いろいろと複雑な処理が書けるようになりますからね。
Httpでアクセスして得た情報を元に、DBに問い合わせをおこなって、さらに結果を元に、特定のページにアクセスするとかできるようになります。

ではでは〜

2011年9月12日月曜日

ConcurrentModificationExceptionに対処してみる。

Mapのデータとかをあつかうときに、全体を検索してみつけたデータに特定の処理をかける…
そんな処理をするときにでてしまうのが、ConcurrentModificationException

問題が発生する原因は、ループをかけているときにマップの要素数が変更してしまうことにあります。

なので、こういうやり方はNG
Map<String, Object> targetMap;
ダメな例その1
for(String key : targetMap.keySet()) {
    targetMap.remove(key);
}
ダメな例その2
Iterator<String> iter = targetMap.keySet().iterator();
while(iter.hasNext()) {
    String key = iter.next();
    targetMap.remove(key);
}
ダメな例その3
for(Entry<String, Object> entry : targetMap.entrySet()) {
    targetMap.remove(entry.getKey());
}
というわけでどんなやり方してもダメです。

ただし例外があります。
1つは、キーセットを元のMapから切り離してしまう方法
for(String key : new HashSet<String>(targetMap.keySet())) {
    targetMap.remove(key);
}
これなら問題なく動作します。

もう1つの例外は要素数を変更したあとに、再ループしない場合です。

for(String key : targetMap.keySet()) {
    targetMap.remove(key);
    break;
}
これなら問題なく動作します。

特に後者はテストで動かしたときに要素数が1つだったりすると問題なく動作してしまうので、注意が必要ですね。

WeakHashMapに関して調べてみた。

Map等をつかっているとデータが消えなくて、よけいなオブジェクトがのこってしまう。
そして最終的にout of memoryエラーがでたアプリケーションが死んでしまうということが多々あります。
かといってMapは非常に使いやすいので(連想配列みたいなものなので)頻繁につかってしまう。

そんなあなたにおすすめなのがweakHashMapを使う方法。
Threadセーフではないのですが、単なる参照としては結構使える。
大元の通常HashMap(ConcurrentHashMapやほかの参照方法でもかまいませんけど。)とそれ以外の部分で参照に使うWeakHashMapの組み合わせ。
これを利用すると、大元のデータを削除したあとにGCがはしればきれいになくなりますのでなかなか使えます。
WeakHashMapを使いたくない場合はWeakReferenceを利用してもOK

とりあえず本日確認したかった事項その1はこれでおわりです。

2011年9月6日火曜日

Jmeterのプラグインを書く、その2

さて、前回では、何もない空のjmeterのサンプラーを書いてみました。
せっかくなので、githubにこの記事にあわせたリポジトリつくってみました。

今回は中身ですね。

Jmeterのエレメントは基本的に3つファイルから成り立ちます。
MyTestSamplerというのがあるとすると、
・動作のベース MyTestSampler.java
・GUI関連の定義 MyTestSamplerBeanInfo.java
・他言語時のメッセージ定義等 MyTestSamplerResource.properties
この3つが一組という感じになります。

とりあえず、MyTestSampler.javaからデータを調査できるようにしてみたいとおもいます。
まず、AbstractSamplerはserialVersionUIDを持つべきなので、適当に追加しておきます。


それから、SampleResultのインスタンスを自分でつくって、sampleメソッドの応答にあてがっておきます。
とりあえずいれておくと便利なのは、
・setSampleLabel リスト上に表示される題目(今回はTestResult)
・sampleStartとsampleEnd この値から実行時の動作効率等を自動で計算してくれます。
とりあえず処理の頭にsampleStart、処理後にsampleEndをいれておけばよいでしょう。
・setResponseData 実行結果を応答します。byte[]で応答するのですが、一番簡単なのは、文字列.getBytes()でいれておくことでしょう。
・setDataType 実行結果のバイトデータがどういうものか指定しないと、まちがった表示になったりします。今回はSampleResult.Textを指定することで文字列で応答することを指定しておきます。
・setSuccessful 動作が成功したか失敗したかの指定です。

プログラムは次のようになります。


ではコンパイルして実行といきます。
とりあえず結果をツリーで表示と統計レポートを追加
 ツリー表示のところには成功をしめす緑の印とプログラムで指定した[TestResult]の文字がならんでいます。
右側の情報のところにはLoadtimeや実行日時、応答したデータの大きさ等の情報がならんでいます。
 タブを応答データに変更すると、きちんと[Sample is ended with success...]という文字列が応答されてます。
 統計レポートを確認すると、50回の試行がなされてほぼ500ミリ秒で動作したようです。
まぁ、500ミリ秒スリープしたからあたりまえですね。

次は、データの入力まわりの追加ですかね。

2011年9月4日日曜日

RtmpClientをつかったJmeterのRtmpSamplerつくりました。

つくっていたRtmpSampler、とりあえず0.1αということにしました。
githubのソースはこちら。

いくつか問題があるので、まずは既知の問題について
・FlashMediaServerにはたぶんつなげない。(Red5のRtmpClientの問題)
・サンプリングツールなのに、大量接続をつくるとjmeterがへばる。(へばらないぎりぎりの線をみつけてください。)(Red5のRtmpClientの問題)
・jmeterがへばるとサーバー(Red5しか試したことないけど)へばる。(テスト後はサーバーを再起動しておくこと。)(Red5のRtmpClientの問題)
・複数のサーバーに接続するテストを実行するとどうなるかわからない。(コネクション情報がおかしくなる?)(Jmeterに対する僕の勉強不足と思われ)

では、リスクについて話したので、自己責任で利用してもらうことにします。
使い方。
1:jmeterのlib/extの部分に必要なjarファイルをぶち込みます。(readme.markdown参照)
2:jmeterを普通に起動します。基本的なJmeterの使い方はこちら
3:適当なスレッドグループを作成して、ConnectConfig、ConnectSampler、DisconnectSampler、InvokeSampler、OnInvokeSamplerを適当に配置する。
4:あとは適当に実行してどのくらいの動作速度がでているか確認する。

では、各部の簡単な説明を・・・
■RtmpConnectConfig接続するときの情報部
variableNameはほかのSamplerがこの接続情報を参照するときに利用するキーワードになります。
rtmpUrlはrtmpでの接続時のURL情報
swfUrlとpageUrlはswfプレーヤーがサーバーに報告する自分のいるページ情報となります。

■RtmpConnectSampler接続を実行するサンプラー
variableNameはConfigで設定した値をいれてください。
timeOutは動作タイムアウトの値ミリ秒で設定します。この図の場合では4秒以内に動作が完了できなかったらタイムアウトとしています。
perThreadの部分は、試行スレッドごとにRtmpClientを作成するかどうかの指定です。
falseにした場合は、1つのクライアントを全体で共有することになります。

なお、接続が確立しているスレッドでこのサンプラーを実行すると、試行をおこないません。

■RtmpDisconnectSampler切断を実行するサンプラー
variableNameはほかと同じ
timeOutもConnectと同じです。
切断を実行します。

■RtmpInvokeSamplerサーバー関数を呼び出すサンプラー
variableNameとtimeOutはほかと同じなので省略
invokeFuncは呼び出す関数名指定
下のテーブルの部分には、関数に渡す引数を指定します。
追加ボタンで追加(追加すると、空白の部分に新たな定義が挿入できるようになります。)
理論的にはいくつでも追加することができます。
また、ほかのサンプラーに後処理の正規表現抽出をいれておくと、ほかの動作で取得したデータをパラメーターに含めることが可能になります。
簡単に解説すると、取得する対象出力をBody(unescaped)を選択
参照に利用する名前を設置(仮にcallResultにします。)
正規表現を追加
$n$をテンプレートを設定$0$でPerlでいうところの$0になります。1つ目の一致結果を利用するには$1$・・・いった形になります。
ほかの場所で利用するには${callResult}という形で記入しておきます。
■RtmpOnInvokeSamplerサーバーからの応答を取得するサンプラー
variableNameとtimeOutはいつものです。
methodNameはサーバーから呼び出されることを期待する値です。
なお、このサンプラーにくる前に取得してしまった場合は別のメモリーにデータをキャッシュしていてそっちのデータがすぐにかえってきます。

実行するとこんな感じになります。

最後に大切なことなのでもう一度書いておきますが、まだ不具合がありますので、実行するなら自己責任でおねがいします。


2011年9月3日土曜日

Jmeterのプラグインを書く、その1

では、一番書きたかったJmeterのプラグインの書き方・・・
ちなみにこの記事の内容は、大本のJmeterのソースコードを解析して、こういうやり方でできるのでは?→できた。という情報なので、完全にただしいかはわからないので自己責任でお願いします。

まずJmeterのプラグインの基本いってみます。
まず適当なプロジェクトをつくる。
Jmeterようのライブラリを追加する必要があります。必要になるのは、ダウンロードしたjmeterのデータのなかのlib/ext/ApacheJMeter_core.jarです。
基本となるSamplerをつくってみます。
クラスを指定、AbstractSamplerを継承してTestBeanをimplementsする必要があります。
するとこんなクラスができます。
このままなにもせずに、exportコマンドでJarファイルをつくってみましょう。
先ほどjarを取り込んだApacheJMeter_core.jarのあるところに出力してください。
この状態でJmeterを起動し、サンプラーの項目を確認すると先ほどつくったMyTestSamplerが追加されています。
 追加してみると項目は次のようになります。
デフォルトなのでなにもないですね。

Jmeterについて

Jmeter・・・apacheのプロジェクトの一部であるこれを使うと、負荷実験ができます。

単にページにアクセスして応答速度をみるだけでなく、一連の動作の実験することができるので結構重宝します。
たとえば、ログインして動作するサイトがあるとして・・・
ログイン→特定のページにアクセス→ログアウト
という一連の流れの動作負荷の実験もできるし。応答データを取得してその値を次の動作に引き継いだりということも可能。
DBのアクセスを織り交ぜることもできるし、FTPやメールもできる。自分でプラグインを追加することも可能だし、サーバー側に設置してCUIで起動して動作テストすることもできるという・・・
こんな便利なツールがあります。


左の[Download Releases]→次のページの真ん中のBinaryの[2.5.zip]でもダウンロードしてください。
ダウンロードが完了したら、適当なツールで解凍し、フォルダ内のbin/jmeter.shやbin/jmeter.batを実行してください。
javaプログラムなので
$ java -jar ApacheJMeter.jar
でも実行できます。

開くと次のような画面のウィンドウが開きます。(画面はMacOSX)
これが基本画面です。
今回はHttpの呼び出しを適当にいれてみようと思います。
なお、負荷ツールなので他人のサイトに変な負荷を与えないようにしてください。
下手すると訴えられます。
今回は1回だけhttp://google.comにアクセスしてどう動作するか確認してみようと思います。
まずは動作スレッドグループを作ります。
こんな感じで追加されます。基本的に上から順に処理されます。
とりあえず、[スレッドグループ]という名前を[Googleにアクセスしてみる]に変更してみました。スレッド数は1つ、Ramp-upは1秒(これは設定したスレッドの作成完了目標タイムです。10スレッドで2秒にした場合、理想動作が0.2秒に1スレッドを作成し起動することになります。)ループ回数も1回だけ

では、Httpの呼び出しを実行したいので、Httpリクエストを追加します。
情報を書き込みます。
Webサーバの項目のサーバー名の部分に[google.com]
Implementationの項目はJava、プロトコルはhttpで指定。
パスの部分は[/]をいれておきます。
動作結果がみてみたいのでリスナーを追加します。
今回は結果をツリーで表示を選択します。
ここまでできたら、テスト計画を保存します。
そのあとで実行→開始を選択します。
すると実行されて、テストの動作詳細が先ほど追加した結果をツリーに表示の部分に表示されます。
Jmeterの基本的な使い方はこんな感じです。
あとは、自分のテストしたいサイトに対して、ユーザーのアクセス数目標等から算出したテスト計画をつくって、応答結果が満足なものになるか確認して、アクセス速度を改善したりすればOKです。