2011年12月23日金曜日

sencha touchのtoolbar

今日はあさから、youtubeのmp4データをjavascriptだけで抜けないかずっとやってました。
結果的には、URLは解析できたんですが、IPアドレス制限にひっかかりましたね。音楽を再生するwebアプリはできないっぽい。中継サーバーたてればいいのですが、それやるとjasracに目を付けられそうだし・・・うーん残念。

さて、sencha touchについて、しばらくまとめようと思います。
今回の記事は一発目、とりいそぎ、toolbarの挙動についてです。

サンプルで作ったwebアプリはこちら。
http://taktodtools.appspot.com/toolbarApp.html
ソースコードに何ができるか等、記述してあります。

要点は。

  • 親要素のdockedItemsにいれればつかえるが、itemsにいれてもOK
  • iconClsによるアイコンの追加はできない。
  • textは無視される。
  • titleは有効で中央に表示される。
  • title内では、htmlタグが有効、ただしaタグ貼ってもリンクにはできない。
  • 子要素のdockedItemsは無視される。
  • 子要素のitemsはボタン風になる。
  • 子要素のitems内では、uiでback forward action等追加スタイルを設定できる。
  • 子要素のitems内では、spacerを挟むと反対側(右側)にアイコンがならぶようになるが、追加はすべて右向き
といった感じでした。

2011年12月19日月曜日

sencha touchのテキストエリア

iPhoneのwebアプリをsencha touchでつくっていて、非常にこまったのが、テキストエリアの取り扱い。

普通にtextareaを置くだけなら、デフォルト動作が発動するので、問題はないのですが、sencha-touchをつかってつくっているといろいろと動作不具合がでてきます。
問題点は

  • テキストエリアの中で行数がふえすぎると、テキストエリアの内部をスクロールさせるすべがない。
  • テキストエリアがおおきく、スクロールして、テキストエリアのトップが上部にはみ出している場合に、文字入力しようとするとアドレスバーがはいってきて、編集できない。
といった問題があります。

というわけで、僕の対処の仕方です。
まず、前者の問題行数が増えすぎて、はみ出るとスクロールできない。
→よって行数がふえたら、テキストエリアを大きくしてやればよい。
textareaでkeyup eventを監視して、行数が増えた場合は大きくしてやればいい。

sencha touchで追加したコンポーネントは直接IDを取得したりする方法がないので、textareaの大きさ変更はtextareaのスタイルシートを書き換えることで実施しています。
テキストエリアのcss設定
textarea {
  height: 100;
}
// cssの要素の大きさを変更するjavascript関数
function changeTextareaHeight(value) {
  var css_list = document.styleSheets;
  if(css_list) for (var i = 0;i < css_list.length;i ++) {
    var rule_list = (css_list[i].cssRules) ? css_list[i].cssRules : css_list[i].rules;
    if(rule_list == null) {
      continue;
    }
    for(var ii = 0;ii < rule_list.length;ii ++) {
      if(rule_list[ii].selectorText == 'textarea') {
        with(rule_list[ii].style) {
          // fontSize = "50%";
          height = value + "px";
        }
      }
    }
  }
}

// keyupのイベント
keyup: function(target, event) {
  // 入力文字の文字列数を確認して、改行にあわせて、パネルのサイズを変更する
  var data = target.getValue();
  var matches = data.match(/[\n|\r\n]/g);
  var num = 0;
  if(matches instanceof Array) {
    num = matches.length;
  }
  if(this.lineNum == num) {
    return;
  }
  this.lineNum = num;
  // パネルの高さx2+文字の高さx改行
  // これをtextareaのサイズにして調整すればOK
  changeTextareaHeight(App.views.viewport.height + num * 24);
}

これで行数がふえればそのままテキストエリアがどんどん大きくなっていきます。
一応問題点もあり、文字が長過ぎて改行文字抜きに改行されてしまった場合。
上記の正規表現からすると、改行とカウントされないのでずれが発生します。

さて2つ目の問題、アドレスバー等がはいってきて困る問題の対処です。
アドレスバーがでてきてしまう問題は、テキストエリアにフォーカスがあたったときに、テキストエリアのちょうど上部の端までwindowをスクロールしてやれば大丈夫みたいです。
よってfocusのイベントでwindow.scrollToを実行します。
focus: function(target, event) {
  var toolbar = Ext.getCmp('editToolbar');
  this.toolbarHeight = toolbar.getHeight();
  window.scrollTo(0,this.toolbarHeight);
},

今回のwebアプリのサンプル(chrome safari iphoneにて動作確認済み)

ではでは〜

2011年12月17日土曜日

sencha touchを解析中。

iPhone用のWebアプリをつくるのに、始めはjqtouchをつかってやろうと思っていたのですが、formのパーツをいれてフォーカスを移動させると動作がおかしくなったり、タイトルバーをださないとボタンが動作しなかったりとちょっと癖が多そうなので、はやめに見切りをつけました。

というわけで、sencha touchを使おうと思っています。
ぱっとみ、kitchensinkというアプリ これが非常に優秀なので、これを参考にプログラムをするつもりです。

というわけで、kitchensinkの構造がどうなっているか、自分用のメモを書いておきます。
プログラム構造
index.html
+ CodeBox.js(ソースコード表示する小窓のデータ:コードの要素解析を実施して、色をつけたりしてる。)
+ index.js(動作の中央部)
+ structure.js(アイテムリストを保持している)

 CodeBoxは要素解析とかいった部分のデータなのでいらないです。
というかiPhoneの選択は、タグを超えて動作しにくいみたいなので、むしろ邪魔。
 indexは動作の中央部。見た目的にNestedListをつかってるだけに見えますが、kitchensinkでは、通常のコンポーネントの組み合わせでNestedListっぽく動作させているようです。
これ、めちゃくちゃはまりました。だって、NestedListだけでつくれると勘違いしてしまったんですから・・・orz
 structureは各リストの内容用の部分です。

Webアプリをつくるwebアプリをつくってみた。

iPhoneを入手しました。
いろいろできて便利ですが、やっぱりこういうデバイスをでたら、それようのアプリを開発したくなります。

ちょっと思いついたら電車の中で、ぱぱっとアプリを書いてみたい・・・
とおもったので、WebアプリをつくるWebアプリをかいてみました。
jqtとはいっていますが、JQtouchのフレームワークをつかってつくってみました。



JQtouchは、フォームの部品があると動作がおかしくなったりするバグがあるしSave,Load,Runのメニューのところむりやりcssを解除してるので妙な動作しますね^^;

jqtouchはさわって3日目ですが、すでにあきてて同じアプリをsenchatouchでつくって、senchatouchのアプリ開発ができるような編集アプリをつくりたいと考えてます。
ではでは〜

2011年12月4日日曜日

ロガーのレベルの振り分け方、個人メモ

最近やってるロガーの振り分け方。

FATAL 全体をとめないといけないような危険な状況。要通知
ERROR 現在の動作ユーザーの処理が続行できない。要通知?
WARN 好ましくない状況が発生、でも動作はする。
INFO 動作段階のメモ
DEBUG 動作中の変数状況のDumpなど

こんな感じが最近のマイブーム。
FATAL、ERRORについては、メールやSyslog、Nagiosに検知を飛ばす等する。
これで想定内の動作のバグ等については、ばっちりかなとおもってるw

2011年11月5日土曜日

Flexの配列について

Flexの配列について、調査してみた。

連想配列
var obj:Object = new Object();
obj["hoge"] = "データ";
obj.hoge = "データ";

連想配列を削除する方法
delete obj["hoge"];

キーでまわす。
for(var key:String in obj) {
}
データでまわす。
for each(var data:* in obj) {
}

通常の配列
var ary:Array = new Array();
ary[0] = "a";

popについて
var ary:Array = new Array();
ary[3] = "a";
ary.toString; // [,,a]
ary.pop(); // aがでてくる。[0,1,2]の要素は影響しない・・・
ary[0]; // undefined

以上メモ

非同期でFLVのパケットデータが送られてくるので、排他処理が欲しいところ・・・orz

rtmfpで高画質配信をやってみたい。その4

実際にrtmfpで接続して配信できるところまできました。
場所やソースは前回と同じところにあります。


Red5用のアプリのソース:https://github.com/taktod/packetTest
Flexのアプリのソース:https://github.com/taktod/packetTestSwf
仮においてみたRed5サーバー:rtmp://49.212.39.17/test/hoge
Flash:http://poepoemix.appspot.com/hqtest/HighQualityMovieTest.swf

やり方は
1:rtmp://49.212.39.17/test/(なにか)にむけて適当な名前で放送を実行する。
2:HighQualityMovieTest.swfを起動してrtmpサーバーの指定を1に合わせてconnectする。
3:rtmfpサーバーに接続し、GroupNameを適当にいれておく。(Cumulusでつくった僕のサーバーがデフォルトで入っています。)

4:別のクライアントで2のプレーヤーを起動する。
5:4で起動したクライアント上でrtmfpサーバーに接続してグループに参加
6:4で起動したクライアントの一番したのButtonをクリックするとグループの他のメンバーにP2P接続を実行し動画の再生を開始する。

というもの。

今後変更しないとだめな部分は・・・
Java側:
・パケットを作成する部分、開始パケットにまだ抜けがある様子。
Flex側:
・再生停止したあとや、グループに再接続した場合等に問題がある。
きちんと初期化されていなかったり、前の命令がのこっていたりする部分がありそう。
・単一ソースからダウンロードを実行しているので、途中の橋渡しをしているユーザーが落ちたら、それ以下のユーザーが全員影響をうけてしまう。
複ソースで動作するように変更したいところ。
・回線の太さによってぶら下がるユーザーの数を上下できるようにしたい。

こんなところか・・・

2011年10月29日土曜日

rtmfpで高画質配信をやってみたい。その3

rtmfpで高画質配信をしてみたいので、最近がんばってます。
その3回目。
とりあえず、flvパケットに変換するサーバーはできあがりました。(まだ動作に不備があるとは思うけどね。)

Red5用のアプリのソース:https://github.com/taktod/packetTest
Flexのアプリのソース:https://github.com/taktod/packetTestSwf
仮においてみたRed5サーバー:rtmp://49.212.39.17/test/hoge
Flash:http://poepoemix.appspot.com/hqtest/HighQualityMovieTest.swf

ルームのhogeの部分を適当な文字に変更してそこに向かって放送を実行。
Flashで同じルームに接続するとflvの断片がサーバーから送られてきて放送が開始されます。


自分の方で動作確認してみたところ、結構なクオリティーの映像が流れました。
あとは、rtmfpにパケットデータをどんどん流して共有するプログラムをかけば、高画質なライブをP2Pで実装できると思う。

flvファイルの解析がかなりできたので、ローカルのファイルをそのままP2Pに流すプログラム(VODの記事みたいに最初から再生じゃなくて、同時進行系の動作)も、書けそう。
Xugglerつかってリアルタイムエンコードして、放送をコンパクトにしたり・・・とかもやってみたいですね。

では、次はいよいよrtmfpに着手だ。

2011年10月28日金曜日

rtmfpで高画質配信をやってみたい。その2

rtmfpで高画質配信をやってみたいので、こんなものをつくってみました。

https://github.com/taktod/packetTest
Red5のサーバーアプリケーションのソースコードです。

  1. このサーバーアプリにむけて何らかの方法で放送を開始する。(接続はデフォルト)
  2. このサーバーアプリの適当なルーム宛にFlashアプリで接続する
すると対象Flashアプリは次の命令を受け取ります。
flvHeader(data:*):void
flvMetaData(data:*):void
flvData(data:*):void
dataはすべてArray(byte[])で送られてきます。
このバイトデータを整形して、NetStream.appendBytesに送ってやると
高画質な再生ができるという寸法です。

H.264、AACの対応が難しくもあり、パズルをとくみたいで楽しかったです。
手持ちの環境では、H.264 VP6 FLV1、音声はmp3、AACで検証確認してあります。

今後実行することは
  1. Flex側のソースコードの公開。
  2. rtmfp経由の動作の実験。
  3. rtmfpをつかったライブチャットサービスの作成と公開
  4. その他rtmfpをつかったアプリの構築
といったところですね。

2011年10月27日木曜日

rtmfpで高画質配信をやってみたい。

rtmfpのサーバーがオープンソースできてしまった上に、放送の実装ができてしまったので、せっかくなので高画質配信をやってみたいと思います。
NetStreamには任意のFLVのデータをappendBytesで追加していってやると動画に変換して放送するという超便利な動作があるので、これを利用してやってみようと思います。
概念的にはこんな感じ。

flvデータをrtmfpで共有してどうこうするというのは、こちらの記事にあります。
オブジェクトデータにして、byteArrayのデータをNetGroupで共有する。
そんな感じの動作です。

FMEやXSplitによる配信データをflvのデータにリアルタイムで変換するというのは、探しても記事がなかったので独自に作成しました。
とりあえずRed5でプログラムをごりごりと書きました。ソースコードは後日githubにあげる予定。
動作概念としては
■サーバー側
1:放送のストリームにstreamListenerをくっつけてパケット情報を監視する。
2:メタデータを受け取った場合はそれを保持しておく。
3:一番はじめのビデオデータ(フレームデータ)を保持しておく。(H.264キーフレーム対策)
4:再生させたい端末(クライアント)がアクセスしてきたら
FLVヘッダ(固定)、メタデータ、フレームデータを送信する。
5:その後は送られてきたパケットデータをクライアントに随時送信する。
で、OK
注意点としては、配信ソフトにはパケットデータを返さないこと(処理量が増えて重くなる。)

■クライアント側
1:NetStream.appendBytesを実行するための準備をおこなっておく。
NetStreamAppendBytesAction.ResetBeginも先に実行してOK。
2:FLVヘッダ、メタデータ、フレームデータ(始めのフレーム)は即netStreamに流してOK
3:しかるべきタイミングでパケットデータをnetStreamに流していく。
H.264の場合、キーフレームを1番はじめにしないとだめ。
H.263やVP6の場合、そのまま流してOK

複数のrtmfpのネットワークに所属するノードがいれば、別のネットワークに又投げしたりできるので、かなり大人数の配信が可能になると思われる。(実質無制限?)

うぉーなんかわくわくしてきましたw。

2011年10月25日火曜日

オープンソースのrtmfp?

今日、同僚に教えてもらったのですがオープンソースでのrtmfp実装がとうとうでてきたそうです。
https://github.com/OpenRtmfp

wireshark等で解析をしようといろいろ情報あつめてたことがあるので、ちょっと興味津々。

node実装とC++実装の2つがあるみたいですね。
とりあえず、低レベルと思われるC++実装の方を選択してみようと思います。
可能なら、Java実装をつくったりrtmfpClientをつくったりしてみたいところです。(後者はFlashの動作を調査しないとわからないかもしれないですね。)

とりあえず、Cumulusの導入してみて、rtmfpの動作確認までいきたいですね。
初回はCumulusのインストールと起動までを・・・

いれた場所はsakuraのvpsです。

1:Cumulusをダウンロードします。
$ git clone git://github.com/OpenRTMFP/Cumulus.git

2:opensslとpocoが必要なので、準備する。
# yum install openssl
でopensslをインストール
pocoはソースをダウンロードしてきてからコンパイルしました。

$ wget http://jaist.dl.sourceforge.net/project/poco/sources/poco-1.4.2/poco-1.4.2p1.tar.gz
$ tar zxvf poco-1.4.2p1.tar.gz

$ cd poco-1.4.2p1
$ make
# make install
で完了。
3:ライブラリパスを通しておく。
$ export LD_LIBRARY_PATH=/usr/local/lib
4:CumulusLibをコンパイル
$ make→パーミッションエラー後
# makeで完了(makeのみでインストールされるらしい。)
5:CumulusServiceをコンパイル
$ makeで完了
6:起動する。
$ ./CumulusService

INFO  Handshake[43] Id of this cumulus server : bb6c0ad01bd6b0dd4290141b34adb8eaca21584744b3d1c6fd513af32e49f947
NOTE  RTMFPServer[101] RTMFP server starts on 1935 port
こんな感じで起動します。

$ netstat -na | grep 1935
udp        0      0 0.0.0.0:1935                0.0.0.0:*       
無事プログラムが起動し、1935ポートのlistenが開始されました。

以上

2011年10月18日火曜日

red5の音声動作にバグあり?

Flazrのライブラリをつかうと、flvをrtmpに変換して流すことができます。

これをちょっと改造して、ネット上にあるflvをrtmpに変換して任意のサーバーに流す・・・そんなプログラムを書いていたのですが、H.264、AACのflvを流しているときに気づいてしまいました。

放送開始まえから、視聴側でplayを実行、再生中にpauseを実行して再度playを実行しても、音声がずっと聞けましたが・・・
放送開始後に、視聴側のstream.playを実行すると映像は見れるのに、音声が流れない・・・
どうやら、途中からplayを開始するとFlash側に音声エンコード情報が届いていないようです。

たしか昔、ClientBroadcastStreamのクラスをいじっていたとき、音声コーデックの情報保持はしていなかったような気がするので、このあたりをもてあそんでやればなんとかなりそうですが、果たして・・・

FlashMediaLiveEncoderのプラグインにAACサポートするのがあって、これを利用すればAACコーデックで音声を流すテストができますので、誰か素敵な紳士・淑女が、Red5の開発陣にバグあるよってレポートしてくれないかなぁ。

ちなみに音声コーデックがmp3なら問題ないみたいです。

ではでは〜

2011年10月4日火曜日

HashMapで文字列キーに対応するデータがとれない・・・あるはずなのに・・・

HashMapのキーの文字列をいれているときに、キー側のデータをStringBuilderで作成したり、通信した後にbyte[]から起こしたりすると、あらたなHashの文字列ができてしまって、参照がおかしくなるときがあります。

こんなときの救世主がinternメソッド。
文字列プール上に展開されている文字列で一致するものを返してくれる。

これをつかえば、確実にキーのhash値が一致するようになるので、データの取得がうまくいくようになります。

これ今日のプログラム変更で非常にやくにたった。
Flexとの通信なんかやってると型変換が内部で大量に発生するので、取得できないデータがぽろぽろとでてきました。

MapをつかうときにはStringのintern()メソッド。
思い出してやってください。

2011年10月2日日曜日

Airで外部プロセスを起動するときのメモ

AdobeのAirで外部プロセスを起動させ、SayKotoeriに発言させてみたくなったので、ちょっとプログラムを書いてみた。

ポイントは2点
・プロセスを呼び出すこと
・suppertedProfilesの記述をapp.xmlの方につけておくこと
です。

とりあえず呼び出すプログラムから・・・
 app.xml側の記述はこんな感じ
これで実行すると「あいうえお」って発言されました。
app.xmlの記述が忘れやすいっていうかわかりにくかったです。

2011年10月1日土曜日

Jmeterのプラグインを書く、その3、データ設定をおこなう。

ひさしぶりにJmeterのプラグインを作成する側の記事を書きたいと思います。

今回はSamplerに設定項目を追加する方法です。

やり方は簡単でBeanのように、設定項目用の変数を準備。
SetterとGetterを配置してやればOKです。

というわけで、TestPluginForJmeterのリポジトリのプログラムにdata1とdata2という変数を追加してみました。

やったことは、変数を追加して、JmeterのGUI上で入力をしておくと、返答結果に入力文字が追加されるというもの。
追加項目が2つでています。2つ目の方は未定義にしてみました。
 実行すると、実行結果の部分に入力したtest1というデータがはいっています。

このJmeterの入力パラメーターですが、どうやら普通の変数ではないようです。
詳細はTableをつかえるようにするときに公表すると思いますが、この動作のおかげでTableEditorをつかった複数項目入力動作の実装がかなりややこしくなっています。
そして今もその設定の仕方について悩んでいたりします。

次に記事を書くとしたら、細かい設定の項目分け方法等ですかね。
では〜

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です。