2010年3月20日土曜日

IE6, IE7 上で flash.net.URLLoader を使って Comet (Long Poling) によるプッシュ通知を行う際の注意点

Flashは一度書いたらどのブラウザでも同じように動く、そう信じていた時が私にもありました。その私の考えを裏切るかのように、 またIEか と言いたくなる現象が発見されました。

調査の際に参考にしたページはこちら。
http://saruzaurus.blogspot.com/2008/07/comet_10.html


■問題
IE6, IE7 で、 flash.net.URLLoader / flash.net.Loader を使用すると、同時に2本しかコネクションが張れません。通常の使い道でしたらこの制限で何ら問題はないのですが、問題になるのは CometTornado のように所謂ロングポーリングと呼ばれるHTTP通信の仕方をするアプリケーションを書いたときです。ロングポーリングではいったんHTTPリクエストをサーバーに投げた後、サーバーで何かイベントが発生するまでそのレスポンスをひたすら待ちます。従って常時HTTPコネクションが1本消費されている状態になるため、事実上1本しかHTTPコネクションを使うことができません。

またIE6, IE7 では、 flash.net.URLLoader.close() の実装にも問題があるようです。
http://www.kirupa.com/forum/showthread.php?t=335691
http://stackoverflow.com/questions/455656/urlloader-gets-stuck-when-polling
きちんと使用後に URLLoaderclose しているのですが、それでも何故かメモリ使用量が減らなかったり、コネクションが閉じられなかったりして貴重なコネクション数が消費されっぱなしになったりするなど、どうにもこうにも不安定です。



これらが原因となって、常時ロングポーリングでイベントを待ち、イベントを受け取ったら処理を行ってまたすぐロングポーリングを張りに行くようなアプリケーションを書くと、その他の通信を行った際にロングポーリングが止まってしまったりその他の通信がコネクション数限界で実行されなかったりします。


■原因
Flashは内部的にはブラウザの機能を用いて実装されています。したがってブラウザ側のHTTP接続数が2本であれば自動的にFlash側のHTTP接続限界も2本になります。当たり前と言えば当たり前なのですが、盲点でした。

Flash側の接続数とブラウザ側の接続数が共有されるかどうかは未知数・未検証ですが、おそらく共有されるのではないかと思っています。従って(まずこんな構成にすることはないと思いますが)FlashでCometによる通知待ちを行い、Ajaxでも同様の通知待ちを行うと、それだけで接続限界になってしまいます。


■対策
今のところ最良の方法がまだ分かっていません・・・ごめんなさいorz 一応いくつか思いついている作戦は、
  1. Windowsのレジストリを操作してIE6/IE7の同時接続数を増やす
  2. 同時接続数制限は同一ドメインに対してのみ発生するらしいので、サブドメインを切って別々のドメインに分ける
  3. 他の通信が発生しているときはロングポーリングを切断する
などなど。上手い対策が発見されましたらまた書きます。

2010/03/31 23:59 追記:サブドメインを切って別々のドメインに分けたら上手く動作しましたので、この方法を一応お勧めしておきます。

2010年3月18日木曜日

Flash の fl.controls / fl.containers の visible プロパティはADDED_TO_STAGEで変更する

最近イマイチなFlashネタしかお届けできておらず残念です>< が、ちょっとしたネタを発見しましたので書いてみます。


■問題
fl.controls.Buttonとか, fl.containers.ScrollPaneのvisibleプロパティをコンストラクタの中でfalseにしても、直後にtrueに戻されてしまうようです。試しに、以下のような構成のMovieClipをFlashで作成して、
  • TestMovieClip
    • aButton
    • aScrollPane
以下のようなコードを書いてみます。
package {
import flash.display.*;
import fl.controls.*;
import fl.containers.*;
public class TestMovieClip extends MovieClip () {
public function TestMovieClip() {
aButton.visible = false;
aScrollPane.visible = false;
}
}
}
このコードを実行すると、なぜかボタンとスクロールペーンが 消えません 。なんでやねん。デバッガを使って調べてみると、どうやらコンストラクタが終わった後、どこかのタイミング?でvisible=trueに戻っているようです。


■対策
以下のようにADDED_TO_STAGEイベントを使って回避します。
package {
import flash.display.*;
import flash.events.*;
import fl.controls.*;
import fl.containers.*;
public class TestMovieClip extends MovieClip () {
public function TestMovieClip() {
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
private function onAddedToStage(event:Event):void {
aButton.visible = false;
aScrollPane.visible = false;
}
}
}
公式のドキュメントを見てもこのあたりの解説が無くて困りました。

2010年2月28日日曜日

Sphinx の Blogger 原稿用拡張を作ってみました

Bloggerの原稿をいちいち手で書くのが面倒だったので(特にリストとかpreとか)、Sphinxを使ってBloggerの原稿を書く拡張を作ってみることにしました。
参考にしたページはこちら。
http://sphinx.shibu.jp/


■サンプルとダウンロード

githubにアップしてみましたので、こちらからご利用いただけます。
http://github.com/akisute/sphinx_rst2blogger

実際に変換させてみたサンプルをこちらに用意してみました。
http://gist.github.com/317478


■設定

完全に私の個人使用向けになっているので、そのままではたぶん使いにくいと思います。まずはMakefileの以下の部分をご自身の環境に合わせて書き換えてください。
blogger:
$(SPHINXBUILD) -b blogger $(ALLSPHINXOPTS) $(BUILDDIR)/blogger
mate $(BUILDDIR)/blogger/draft.txt
@echo
@echo "Build finished. The draft pages are in $(BUILDDIR)/blogger."
今私は mate コマンドを使って結果をTextMateに表示するようにしていますが、これはTextMateがないと使えないので適当に消すなり pbcopy に書き直すなりすると幸せになれます。

また、Blogger側の以下の設定を有効にしてください。



■実際に使ってみる

使用方法はとっても簡単です。以下のコマンドをシェルから実行してください。
make blogger
make.batは全く操作していないのでWindowsの人はごめんなさい。たぶん使えません><

また、100%完璧な変換はできておらず、主にpreとかtitleの箇所で手動微調整が必要になります。まぁおおよそ上手くやってくれればいいや、という考えです。


■おまけ:Sphinxの拡張機能でカスタムのビルダーを作る方法

拡張機能の作り方自体は以下のページのやり方に沿えば楽勝です。
http://sphinx.shibu.jp/extensions.html
ですが、肝心のビルダーを作るのはかなり苦労しました。

ビルダーの作り方ですが、一から手で書くと挫折するので、もともとSphinxに付いているビルダーをまるごとコピーしてそれを修正するようにすると比較的楽でした。リファレンスとかドキュメントとかないので、ソース見て、 visit_hogehoge とか depart_hogehoge とか書いてあるところを適当に修正してみたら動いた、って感じです。 TextBuilder を元にすると書きやすかったです。 HTMLBuilder はdocutilの機能を拡張しているためdocutilがわからないとさっぱり分かりません。