PHPだけでリアルタイムAJAXチャットシステムを構築する方法。

PHP, JavaScript, AJAX, Comet

08:41:06, by dozo Email , 99 words, 20412 views   Japanese (JP) del.icio.us

言語はぶっちゃけなんでも良いってわけだ。

(ノ・・)ン。。。。。。(((●コロコロッ

まずは、現物から。
複数起動したブラウザからそれぞれアクセスして、
右側のボックスに文字を入れて叩くと内容がシンクロしている・・・と思う。



取りあえず動くところまで作成。
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のタイムスタンプ変更を追加するのがいいかな。


・再接続時のアクセス集中
コネクションを張りっぱなしのこのシステムだが、
問題は内容が更新された直後。
一度切断して、もう一度接続するという作業を、
接続している該当人数分行うことになるので、
多大なアクセス集中を招くことになる。

ちっちゃなアプリやウィジットぐらいなら、
そもそもコネクション数が多くないので気にはならないが、
規模が大きくなるとその部分の影響力は大きい。

回避策はちょっと難しい。
データを更新するのを、
多少前後させるすればなんとかなるかもしれないが、
それではリアルタイムの意味が無くなる。
台数をそれなりに用意することで解決するしかないのかな。



参考:


Trackback address for this post:

http://hain.jp/htsrv/trackback.php/195

Comments, Trackbacks:

No Comments/Trackbacks for this post yet...

Leave a comment:

Your email address will not be displayed on this site.
Your URL will be displayed.

Allowed XHTML tags: <p, ul, ol, li, dl, dt, dd, address, blockquote, ins, del, span, bdo, br, em, strong, dfn, code, samp, kdb, var, cite, abbr, acronym, q, sub, sup, tt, i, b, big, small>
(Line breaks become <br />)
(Set cookies for name, email and url)
(Allow users to contact you through a message form (your email will NOT be displayed.))
This is a captcha-picture. It is used to prevent mass-access by robots.

Please enter the characters from the image above. (case insensitive)

powered by b2evolution

shinobi

Neighbors
Relative
Favorites

極論istの技術屋を始めて早幾年。 流れの速い業界の波にもまれながらも精一杯生きている様をとくとごらんあれ。

Archives
スポンサー

Latest bookmark
Search

Categories

Who's Online?
Misc
Syndicate this blog XML

Valid XHTML 1.0! Valid CSS! Valid RSS 2.0! Valid Atom 1.0!