c/fe

http://d.hatena.ne.jp/uzulla から移行しました。

Twitterに投稿されたTwitpicの画像を超低レイテンシでガンガン表示する。

昨日も書いたけれど(http://d.hatena.ne.jp/uzulla/20100211#p2)、これの少し解説というか俺のメモというか。
http://www2.himitsukichi.com/~zishida/tp/sample.html

仕組み

Perlで組んだバックエンドとFlashを通信させ、Flash側で受け取ったTwitpicのID( /http://twitpic.com/($w+)/ )を片っ端からFlashに投げて表示している。
TwitpicのサムネイルのURLとか、いろんな仕様はパクり元のゆーすけべー氏作の http://picstream.pulpsite.net/ から知った。


PerlのバックエンドはTwitterのStreamを受け取りつつ、デーモンとして動作していて複数接続を処理している(一人しかしゃべらないチャットサーバーみたいなもの)。
Flash側はまったくひねりなし、どんどん表示してタイマーでどんどん消しているだけ。


この構成で、試した限り、投稿ボタンをおして1秒以内に画像が表示される。しかも全世界的な投稿が同様だと思うと、自己満足は十分できた。

Perlのバックエンドについて

まず、AnyEvent::Twitter::Stream*1をつかってTwitter Streaming API に接続し、twitpicというキーワードをtrackしている。取り込みのコードはほとんどサンプルコードのママだが、一部こちら(http://www.omakase.org/perl/anyeventtwitterstream.html)のコードを参考にしている。


on_tweet => sub { } が呼ばれる度に、正規表現でTwitpicのIDを抜き出して、接続している全員にforで回してpush_write()している*2
コネクション管理(というかファイルハンドル管理)は、こちらを(http://unknownplace.org/memo/2009/12/07/1/)かなり参考にした。


ファイルハンドルのリストをStream リーダーとデーモンのTcp_serverの間で共有しないといけないが、スレッドみたいにsharedとかしなくても配列ならそのまま相互間で参照しあう事ができた(当然か)。
ただ、AnyEventのオブジェクトを生成するときに、登録した関数はクロージャになるので、単なるスカラ変数(カウンターとか)はリファレンスつかわないとダメだった(これまた当然か)。


まーとにかくスレッドとは違う、当たり前だけど。最初スレッドのノリでかいてて迷走した。
普段クロージャを使わないので(最近PHPばっかり書いているので)一瞬ハマったが、AS3やJSの感覚を思い出したらあっさり解決した。

Flash側について

socketをnewして接続してデータ待ち受けて、うけとったTwitpicのIDを、生成したImageにSourceしてAddchildしていろんなHandlerとTimerをセットするだけなので、割愛。


Socket接続するので、Socket Policy Fileをポート864でレスポンスする奴だけ置いた*3

AnyEvent::Twitter::Streamすごい

AnyEvent::Twitter::Streamは良くできている。Twitpicをtrackすると普通に10Post/secくらいのストリームは来るのだけれど、遅延やもたつきもなく、ちゃんと名前とかTweetとかがParse済みのデータが受け取れるので、もうなーんにも考えずにどんどん書ける。すばらしい。
(ちなみに、その時のCPU負荷はCeleron 750Mhz(笑) 1GB memoryのLinu 2.4箱で4~10%くらい。低スペックサーバーでも十分回る)

AnyEvent::Socket::tcp_serverすごい

サーバーとして待ち受けたり、エラー処理(切断処理)とかもものすごく楽にできる。push_writeの楽さもいい。
まあとにかく考える事が無い。

つまりAnyEventすごい

ホントいまさらというか情報おせーよ(調べる情報はどれもこれも半年〜1年くらい前のポストだったので)という話なんだけれど、改めてすごいなーって思った。

こういうサーバーコードはスレッドでかかなきゃいけないんだ、という先入観たっぷりだったが、イベント駆動のコードは安全なので、とても書きやすかった。
いままでFlash間をサーバー経由で同期させるのに、Red5とかでリモート接続してSOを共有したりしていたけど、こっちの方が開発が楽で早くて負荷も低くくて、あげくPerlだから楽しいのはすごい。


まあ、Red5やFMSはsocket特有の面倒な所*4が隠蔽できてるけど、それにしたってBrazeDSみたいなxml地獄もなく、書いたら書いたであっさりうごき、プロトタイプがすぐ書けるのはすばらしいなー。
(そういえば、さすがに AnyEvent::rtmpはなかったな)

やっぱPerlいいな

最近PHPばっかりやってたけど、Perlもいいなあ…。
Mooseに慣れられれば、もうすこし色々書いてもイイかなあ。

しかし、本来の目的のテストは出来なかったw

まあ、こんな怪しい、二番煎じサービスですしね…。
TLに書けば、同時に10人くらいはつないでくれるかなーっておもったんだけど、ものすごく控えめにpostしたのも悪いが、全部あわせて10人くらいにしかつないでもらっていないw
うーん、とりあえずApacheBench改造して、同時1000接続くらいでスルスル吸う奴を作るかなー…。サーバー側だけテストできればいいし。それこそAnyEvent::socketで書くべきだろうか