ErlangでComet
ErlangでCometしてみた.
(iframe方式は結局だめそうなので,Cometに)
実装はきわめて手抜きです.あくまでサンプルとして.
ソース:
chat.erl (22行.etsテーブルの初期化)
chat.yaws (72行.サーバ側の実装)
index.html (52行.HTML+JS)
※別途jqueryが必要
こんだけ短いソースでも,ちゃんとCometできるし,C10Kにも対応できる.(問題はいろいろあるコードだけど)
いろいろちゃんと実装したとしても,かなりシンプルに仕上がると思う.
Comet の正しい使い方で紹介されているプログラミングモデルのどれにも当てはまらない新しい方式,といえるかも.
Cometのために特殊な実装をする必要もないし,I/O多重化など実装がめんどくさい手法を使う必要もない.
普通に各リクエストの処理を書いて,新規メッセージを待つ部分ではそのまま待つコードをかける.
なお,yawsでそのまま実行すると,PIPELININGの相性問題が生じます.
yawsのソースの yaws.erl を
yaws.erl: ["Server: Microsoft-IIS/5.0; Yaws/", yaws_generated:version(), " Yet Another Web Server\r\n" |
というように書き換えれば解決.
最初HTTP/1.1を1.0に書き換えたのだけど,IE6でうまく表示できなくなってしまった.
1.0なのに1.1規格onlyな応答を返したりしていたせいかもしれない.
上のIISを騙る方法では無事成功.IE6/IE7/Firefox/Operaでは動作確認できた.
この辺は,Comet の正しい使い方,が大変参考になりました.
----
追記:改良した.
入退室管理,時刻表示,などをつけて,色々まずかった部分を修正.
だいぶソースは長くなったものの,Erlangが250行弱に,HTML+JSが100行くらい.
ソース:
chat.erl (ログの管理など)
chat.yaws (HTTP処理)
index.html (HTML+JS)
※別途jqueryが必要
----
追記:更に改良した.
・IE7利用時にクッキーの管理がまずく,うまく入室できない事がある問題を修正
・ログをdetsで保存するようにした.再起動してもログが残るように.
・ログの保存量を100行に.1000行だと,チャット画面を開いたときに重そうだったので.
JSONで返したのをブラウザで描画するのではなくて,HTMLに変換済みのデータを最初に渡すようにすれば改善できそうだけど,めんどくさそうだったので(^^;
ソース:
chat.erl (ログの管理など)
index.yaws (HTTP処理)
index.html (HTML+JS)
※別途jqueryが必要
ソースはerl+yawsで270行くらいになった.
----
追記:
色々修正した.
・デザインをちょっとだけ.参加者一覧が上にでるとじゃまなので・・・
・発言と同時に誰かのタイムアウト処理がされたときなどに,2回連続で再接続させるのは無駄なのでタイミングを調整
・発言が続くとタイムアウトしない問題を修正
・入室直後に参加者一覧に追加されない問題を修正
・チャットの部屋をブックマークして再度参照した場合,クッキーの関係で正常に処理されないことがあったので,リダイレクトさせるのをやめた
・同じ名前で入った場合,重複しない名前をつけるように修正
ソース:
chat.erl (ログの管理など)
index.yaws (HTTP処理)
chat_temp.html (HTML+JS)
※別途jqueryが必要
ソースが300行を超えた.
とはいえ,他の言語でやることを想像したら,かなり短いコードで書けているとは思う.
一応,簡単な負荷試験として,
chatbench.erl
とか書いて,1000人がROMっている状況でテストしてみたところ,まぁ普通に動いていたので,
そのくらいまでは耐えられそう.
Windows上で実験していたら,ポートが不足したのか,しばらくやるとクライアント側がエラーを出していたけれども(^^;
----
JSONP方式に切り替えた.
JSONP+CometはOperaでは無理と思っていたのだけど,下記を参考にさせていただいたところ,ちゃんと動くようになった.感謝.
Operaでも非同期リクエストが並列処理できる img-JSONP
IMGタグでキャッシュさせるというアイディアがすごい・・・
ソース:
chat.erl (ログの管理など)
index.yaws (HTTP処理)
chat_temp.html (HTML+JS)
※別途jqueryが必要
今のサンプルは,ドメインが1つだけども,リロードするたびに適当なホスト名を生成して,ワイルドカードドメインを使えば,ドメインあたり2接続の問題は回避可能.
これでなんとか解決かな?
Safariで動作確認取れていないのが気がかりなところだけども・・・
% Mac持ってないので(^^;
追記:設置方法を別エントリに書きました.
ErlangでComet設置方法
The comments to this entry are closed.
Comments
私も最近、ErlangでCometなチャットサービスを試作してみたんですが、みかさんのページを見ていたらいろいろ気になりました。私はT-Coderだし、Ajaxと戻るボタンの履歴について最近調べていたし、Erlang勉強中だし、いろいろ似たことに興味を持つ人がいるんだなぁと思ったのでした。Perlも好きです。なにかある種の指向というものがあるんですかね。
とりとめないコメントですが……。
Posted by: rui | Friday, May 04, 2007 10:01 PM
確かに似てますねー.
他にも似たような人はいるのかもしれないですが,身の回りでErlangに興味を持ってる人はあまりいないかなぁ...
Erlangは日本語の情報が少ないのでなかなか勉強がはかどりません.
英語苦手なので(^^;
Posted by: みかげ | Friday, May 04, 2007 10:15 PM
初めまして NUMA と申します。
最近、Erlang が注目されているので、みかさんのブログを読ませて頂き、先程、Comet チャットサンプルも試させて頂きました。
私は検証も兼ねて VMWare のゲスト OS として Ubuntu Linux を利用しているのですが、
Ubuntu からホスト OS の AirEdge 経由でも反応が速かったです。
Erlang の詳細まで追えてませんが、こんな少ないコードで Comet が実現できるのは凄いですね。
Posted by: NUMA | Friday, May 04, 2007 11:54 PM