言語はぶっちゃけなんでも良いってわけだ。
(ノ・・)ン。。。。。。(((●コロコロッ
まずは、現物から。
複数起動したブラウザからそれぞれアクセスして、
右側のボックスに文字を入れて叩くと内容がシンクロしている・・・と思う。
取りあえず動くところまで作成。
Cometの様な大がかりなものではなく、
表示用のページ一枚と、
コネクション維持のプログラム一つだけ。
特徴は
- 非常にシンプル
- 共有サーバでも設置可能(サーバ会社から文句言われるとかは除く)
チャットのソースはこんな感じ。
RealTime Ajax Chat Connection Source
RealTime Ajax Chat View Source
セキュリティは厳重ではないしバグもいくつか見つけてるけど、
特別修正する気はないので再利用は自己責任でよろしく。
一見長いように見えるが、
ほとんどがオブジェクト永続化に使ったCache_Liteの設定・利用まわり。
そこは全然関係ない。
Comet(Real time AJAX)だが、
一年ほど前、みな一生懸命研究していたような気配だった。
一度下火になったようだが、
ここ最近、またCOMET熱がよみがえっているようで、
最近のAJAXフレームワークにはサーバプッシュ系実装が増えてきている。
私も過去にいろいろ試した。
OperaのServer-Sent Event, Firefoxのmultipart/x-mixed-replaceはちゃんと動作するものの、
どうしてもInternet Explorerがネックになって先に進めなかった。
代わりの方法でFlash+Javascriptで実装してみたわけだが、
動作はしたものの実用性は皆無。
それ以降は手を付けていない。
(最近
アシアルブログで取り上げられていたが。)
時間的コストが高すぎるのでAMFは試していない。
あれこれ調査していると、
一つ面白い手法にたどり着いたので、
それに関するブレスト。
この手法なら、
が解決出来る。
実用度には議論・検証が必要だが、
いろいろ実験してみて答えを出すことにしよう。
[More:]
GmailやMeboo、最近のAjaxフレームワークが採用しているのは、
htmlfileというパラメータでActiveXObjectを生成する方法。
IHTMLDocument2が生成されて、
そこに仮想的なiframeを構築し・・・どうのこうのらしい。
私は、今までコネクションを継続している無限ループの中で情報をはき出し続けるイメージを持っていた。
コードにするとこんな感じ。
ob_start();
while( true ){
echo 'データ出力';
ob_flush();
flush();
sleep(1);
}
ob_end_flush();
SSEやmultipart/x-mixed-replaceはこの手法を使っている。
しかし、このチャットシステムはそこが根本的に違っている。
無限ループは保存データファイルが変更されるまで、
ひたすらループを繰り返すだけでデータ出力は一切しない。
変更があった時にデータをはき出してプログラムを終了させている。
コードにするとこうかな。
while( /* 更新待ち */ ){
; // 何もしない
sleep(1);
}
echo 'データ出力';
なんの変哲もないただの無限ループ。
この
プログラムを終了させる
というのがポイント。
IEで問題になっているのが、
バックエンドプログラムが継続中はデータ更新されない
こと。
であれば、コネクションを切断すれば更新されるわけだ。
(´・ω・) リアルタイムジャナイジャン
コネクションを一度切断すると、
JavaScript上のonCompleteが起動し再びコネクションを張る。
それにより、コネクションの永続化を仮想的に実現させているわけだ。
なかなか面白い。
これなら単調な無限ループ+単調なAJAXの組み合わせでシステムが組めるので、
JettyやTwisted、POEなどアップリケーションサーバが不要。
使用言語に依存することはなくなるわけだ。
また、ブラウザ依存問題が発生しない。
IEだけ特別な方法を用いる必要が無くなる。
Cometといえばチャットでは●島健●郎なみに芸がない。
なにかいろいろ考えることにしよう。
考察:
・バックエンドのデータベース連携
サンプルでは保存しているデータファイルの日付を延々眺めていたわけだが、
実際はデータベースを利用することになる。
となると、無限ループ中Selectが走りまくることになり、
データベースサーバの負荷増大に繋がる。
さらに、ネットワークがあっという間にパンクする。
回避策は今のところ見つかっていないが、
memcachedをそれぞれのサーバに載せ、
データ連携を計るというのはどうだろうか。
データの中に更新日付を持っておき、
それが更新されるまでローカルサーバ内のmemcachedをみる。
更新通知をすべてのmemcachedに行えば、
他は自動的に動き出す。
・・・どうかなやってみないとなんとも。
データベースのトリガーを使って外部プログラムでも呼び出せれば良いのだが。
insertやupdateのプログラムにmemcachedのタイムスタンプ変更を追加するのがいいかな。
・再接続時のアクセス集中
コネクションを張りっぱなしのこのシステムだが、
問題は内容が更新された直後。
一度切断して、もう一度接続するという作業を、
接続している該当人数分行うことになるので、
多大なアクセス集中を招くことになる。
ちっちゃなアプリやウィジットぐらいなら、
そもそもコネクション数が多くないので気にはならないが、
規模が大きくなるとその部分の影響力は大きい。
回避策はちょっと難しい。
データを更新するのを、
多少前後させるすればなんとかなるかもしれないが、
それではリアルタイムの意味が無くなる。
台数をそれなりに用意することで解決するしかないのかな。
参考: