2008年01月30日

JSONP時のエラーハンドリング

jQueryでJSONP形式での通信時にエラーが発生してもerrorで指定した関数を呼んでくれない。
ふぬぬ。これではサーバエラーが発生したかどうかわからないではないか。

JSONPをどのような形で実装しているのか知らないが、XMLHttpRequestとは違い、エラーのハンドリングがそもそもできないようなやり方でやってるとかかな。<script>タグの動的追加で実装してるならハンドリングはできなさそうだが。

2008年01月28日

チャットルームDB永続化完了

とりあえずチャットルーム情報をRDBに保存し、チャットルーム情報編集時に保存、サーバ起動時にDBから復元するようにした。
さらにチャットルーム作成、編集、削除画面作成。
Ajaxを使ったチャットルームとは対照的に壮絶にシンプル。
livechat2.png
まぁ誰も見ないページだから適当でw

設定画面は削除確認画面とかめんどかった。
かといって確認画面を作らないと間違って消してしまったりしそうだからなぁ。

2008年01月25日

Springの本

現在開発中のチャットプログラムの開発は、Struts + Spring + iBATISで行っている。
WebアプリケーションフレームワークにStruts、DIコンテナにSpring、O/RマッピングにiBATISだ。

Springに関する本を持っていなかったため、Webの情報に頼っていたが、やはり何か本を買った方がいいなと言うことで、以前図書館で借りたことがあるJava・J2EE・オープンソース Spring入門を購入。
Java・J2EE・オープンソース Spring入門 ~より良いWebアプリケーションの設計と実装
読み返すと以前は返却期間もあって読み切れてなかったのか、今だからこそわかる発見みたいなのが合ってよかった。

内容は「入門」とあるように、全くの初心者にも優しい内容でわかりやすかった。
第1章はそもそもWebアプリケーションとは何か、なぜSpringのようなDIコンテナが必要になったのか、その歴史から解説してあるのでWeb開発初心者に優しい。ただしJavaの知識は求められる。Javaと言うよりオブジェクト指向か。安定依存原則、依存関係反転原則を実現するためにあると。これらの原則はこの本では軽く触れられている程度なので深く知りたい場合はプログラマのためのJava設計ベストプラクティスが詳しい。

そのほかSpringの導入と設定方法、DIとはどのようなもので、使うとどのような問題がどのように解決するか。Springによるアスペクト指向プログラミング(AOP)のやりかた。ここも、ある問題があり、それをどのようにAOPが解決してくれるかを提示してある。ちなみにAOPのサンプルとしては例外処理をAOPで解決するというのが例で出ていた。後はSpringによるDBトランザクションの管理、SpringとJDBC、Hibernate、iBATISとの連携方法の紹介。Hibernateは現在の最新である3系ではなく、2系を使用している。

これ一冊でDIとは何か、どのように使うとどのように便利になるのか、AOPとは何か、各種O/RマッピングフレームワークとSpringによるDBへの永続化の初歩などが理解できる。

が、やはり「入門」なので、そこから先に進もうと思うとこの一冊では当然物足りなくなる。
よって一緒にSpringによるWebアプリケーションスーパーサンプル
を購入したつもりだったのだが、StrutsによるWebアプリケーションスーパーサンプル第2版
を買ってしまっていた・・・orz
StrutsとSpringを見間違えていたようだ・・・。
まぁStrutsもそれほどディープに理解しているとはいえないのでこれを機にもうちょっと深く勉強するか・・・。

NDS復活

DSがぶっ壊れたので修理に出して、そして戻ってきた。

どう壊れたかというとACアダプタをさしても充電できず、そのまま電池切れで使えなくなってしまっていた。
買って1週間後ぐらいに一度その現象が出て、本体をバシッと一発しばいたら復活したのだが、その数週間後にまだ同じ現象が出て今度は何度気合いを入れても復活しなかった。
結局買って1ヶ月ぐらいで永眠。
その後、数ヶ月放置していたんだけどいい加減修理しようということで修理に出した。

が、修理結果は「現象が再現できず、検査の結果も異常無しでした。しかし念のため新品と交換しました。」とのこと。

新品になったので良かったんだけど、なんか腑に落ちない・・・。

2008年01月24日

Twitter始めました

http://twitter.com/kenji1203
です。

人が増えるほど楽しいと思われるので気が向いたらどうぞ。

2008年01月19日

JSONP対応完了&オペレータ機能

チャットサイトのJSONP化が完了した。
これでIEでも完璧に動作させることができた。
ついでにjQueryのフェードイン機能などを使い無駄に表示を派手にしてみた。

さらにオペレータ機能も追加。
チャットルームに常駐しているオペレータの人工無能に対し自然言語で話しかけることによってオペレータに対し指示ができる。現在はチャットルームのサブタイトル変更を指示することができる。
たとえば「サブタイトルを「Cometチャット!」に変えて>オペ子」とチャットで発言することにより変更が可能だ。
ope1.png

オペレータへの入力は、文末に「>オペ子」をつけることによって入力となる。
オペレータに対して入力された文章は、形態素解析器Senによって形態素に分割され、処理される。
といっても現在は"サブタイトル""変"が発話に含まれているかだけしかみていないが。
より良い実装のアイデアとしてはコマンド入力例を例文として多数用意しておいて、ユーザの入力文の形態素解析結果をベクトルとしてベクトル空間上でのコサイン距離を測ることによって一番近いコマンドを判断するという感じか。

複雑なことをしようと思うと形態素解析だけでは不十分で、構文解析も必要なんだけどJavaから利用できる構文解析器が無いため現在はしていない。
使うとしたらCaboChaあたりをサーバ化して、TCP経由で構文解析をするって感じだろうか。


チャット機能はIE対応をもって完成したわけだが、チャットルームやそのサブタイトルなどの情報の永続化ができていない。
これらはRDBに保存するのが楽かな。
よって部屋のメタ情報はMySQLに入れ、ログの情報はファイルに書き出すことにしよう。
起動時はDBから部屋の情報を取り出し、最終状態に復元するという感じで。

一人でこういうシステムを作成しようとすると、プログラミングの知識はもちろんOS,Webサーバ、アプリケーションサーバ、データベース、通信プロトコル、ネットワークその他諸々の知識が総合的に必要なのでそれらの学習コストが大きく大変だな。それがおもしろくもあるけど。
まぁ広いジャンルでの経験値が得られるので良いことだ。

2008年01月17日

jQueryでAjax

現在作成中のチャットサイトにはAjaxのライブラリとしてPrototypeを使用しているが、いろいろ調べてみるとjQueryが高速軽量でいい感じらしい。
JSONPが簡単に使えるのもいいな。
また、魅力的で豊富なプラグインがそろっているのもすばらしい。
現在それほどPrototypeに依存しているわけではないので、JSONP対応を機にjQueryに移行しよう。

jQuery で JSONP 2通り
[JS]jQueryのプラグイン33+1選 -2007年11月

まずはjQueryに移行してからJSONP対応をするか。

2008年01月16日

IE問題の解決策

IEでCometを実装すると問題が発生する件は、回避策がいくつかありそうだ。
1,チャットルームへ入るたびに新規のサブドメインを割り当てる。
2,JSONPを使う。

世の中的には2のJSONPを使うやり方が一般的のようだ。
JSONPはXMLHttpRequestに存在する他ドメインへのアクセス制限を回避することができる。
が、JSONPはXMLHttpRequestと違いタイムアウトなどエラー時のハンドリングができない。Operaで動作に問題があるなどするようだ。Operaでの回避策は一応あってOperaでも非同期リクエストが並列処理できる img-JSONPを参照。

ふーむ、1のやり方で回避できそうな気もするけど・・・。
Lingrは発言などの投稿はwww.lingr.comへ。新規ログの取得はランダムサブドメインを読むようにしていた。別ドメインにアクセスしに行っているからJSONPだろうか。JavaScriptのソースは読んでないので推測だが。

JSONPを導入するとopera対応も必要だし、とりあえず部屋に入るときにランダムサブドメインを生成するページを経由し、その後そのドメインを使用した部屋にリダイレクトするようにするか。
その後、何か落とし穴があるようだったら素直にJSONPに移行しよう。


というわけで、リダイレクトを使って動的にサブドメインを作るやり方でIE問題を回避した!
これによりIEで部屋の出入りをしてもセッション数制限で不具合はでなくなった。

が、F5でリロードしてしまうとセッション数が足りなくなってやはり問題が・・・。
F5禁止にするかJSONPにするか・・・。
やっぱJSONPが無難かな・・・。

2008年01月15日

IEとCometの相性

IEでHTTPセッションを張りっぱなしにする問題で検索していたら以下のページが見つかった。
IEとCometの相性が悪い

やはりIEでCometは問題があるようだ。
確かにLingrではチャットルームに入るたびにサブドメイン名が変わっている。

IEで使えないと話にならないので対応するしかないようだ。
一度、ランダムなサブドメインを生成するページに飛んでから、そのランダムなサブドメインでチャットルームにリダイレクトするページを作らないとだめなのか。
めんどくさいが仕方あるまい。
まぁ解決策がわかったのでよしとしよう。
しかし部屋ごとにサブドメインを分けるのには気がついたが、部屋に入るごとにサブドメインを生成するのに気がつかなかったのは悔しいな。

2008年01月14日

Kinesis来た

先週の月曜日に到着予定だったけど家に誰もいないので夜に配達してもらおうと電話すると、なんと平日は配達時間の指定ができないといわれた。よって受け取れたのはこの週末。
時間指定ができないなんてひどい話だ。
どうも今回はUPS直属の配達業者ではない様子で別の聞いたことも無いような業者が配達していた。

ということでAdvantage Proを我が家に導入。
DSCF0515.JPG
Advantage ProはSingle Action Foot Switch(足踏み式スイッチ)がついているのだけど、予想通り足でのスイッチは使いづらいことこの上ない。指と違って足は細かい動作ができないのでゲームで何かのマクロを割り当てて使うぐらいか。

外観はメタリック塗装ということで写真の通り。
写真では質感がざらざらな感じがするけど、表面に薄く透明なコーティングがされてるような感じでツルツル。塗装されているので塗装がハゲたらやだなと思ったが大丈夫そうだ。
キーのスイッチは同じのはずなんだけどKB500よりもキーが重い感じがする。最初だけかな。

まぁとにかくこれで家でのプログラミング環境が改善された。


次はトラックボールを家にも導入したいな。

2008年01月12日

ログの永続化

さて、「今年はやるぞ!」と書きつつも仕事が忙しくて全然プログラミングが進んでいないわけですが、間を開けるとまたモチベーションが下がってしまうのでちょっと手を出してみる。

しかし相変わらずIEでは動作が怪しい。
発言しようとしても同時セッション数制限で発言用HTTPセッションが張られず、発言ができなかったり、そもそも部屋に入れなかったり・・・。
ログ取得用と発言用のドメインを分けようとしてもJavaScriptからはセキュリティ上の制限で同じドメインのサーバにしか接続することができないからなぁ。
まぁとりあえずその問題は置いておいて、作るのを進めるとするか。


現状のチャットでは、ログの永続化がされていない。
よってサーバを再起動するとログが消えてしまう。
今回はこれの永続化をやってみよう。

現状のチャットサイトではMySQLを使っているが、チャットのログなど読み込みよりも書き込みが激しいデータはRDBに入れるのはまずいだろう。なぜかというと読み込みが多い場合、MySQLのサーバをクラスタリングなどすれば楽に対応できるけど、書き込みの場合はそれができない。普通にクラスタリングをしようと思うとレプリケーションになってしまい、書き込みサーバを増やすことができないからだ。

よって先人に学び、ニコニコ動画のログのようにCSVで保存しよう。
XMLなどリッチな形式にしようかとも思ったけど、チャットのログのデータ形式が激しく変わるとも思えないので単純にCSVで。
CSVならログの追加もファイルに追加していくだけなので楽だ。
単一のファイルならでかくなって困ることがあるので、毎日ファイルのローテーションを行うと言うことにしよう。さらに速度確保のため保存処理は一定間隔毎とし、ユーザの発言処理で発生するIOはメモリのみと言うことにする。

と言って保存したところで読み返すことは無いと思うが・・・。
荒らし対策にIPアドレスの記録がメイン目的と言ったところか。


以前のチャットルーム参加者人数が減らない問題は新規ログの取得が一定時間無いと退出したと判断。
一応チャットウインドウを閉じたり、他のページに遷移するとログオフイベントを投げるようにしているがうまくいかないときもあるようだ。

2008年01月09日

今年の抱負

さて、とうとう2008年が始まったわけですが、何かしら目標を立てないと無駄に時間が過ぎてしまうのでここに決意を明文化し公開することで背水の陣で行こうかと。

今年は何かのプログラムを作りきる年にしたいな。今までは自分の中で満足してしまったらそこで開発をやめてしまって、それっきりと言うことが多かったからな。公開せず自分だけで開発しているので、"新しい技術を使う"という目標が達成されればモチベーションが急激に下がって開発が止まってしまう。しかし、それを外部に公開することで他の人からの意見を聞きつつモチベーションも維持できるというわけだ。たぶん。

今年は二つのプログラムを作りきろう。
一つはこの正月にアップしたチャットサイト。チャットの部分はさくっと作れたが、それ以外にもアイデアがあるのでそれを盛り込みたい。
もう一つはメモソフト。現在emacsのChangeLogを使っているが、壮絶に使いづらい。もっと高機能なメモが欲しい。今すぐにでも欲しい。探せば有料ソフトとかでもありそうな気がするが、せっかくプログラミングができるので作ってしまおう。

あと、それらの作業工程もブログに書くことでモチベーションをあげることができるかもしれないな。


まぁぼちぼちがんばっていくかー。

2008年01月04日

AjaxとCometを用いたチャットサイトを作った

この正月ひたすらプログラミングしてCometを使用したチャットサイトを作った。
http://anime-freaks.net/chat/

チャットルームは以下のような感じ。クリックで拡大。
livechat1.png


Cometとはプル型の通信しかできないHTTPの使い方をちょっとひねって、サーバ側からプッシュ型の通信をできるようにした技術。
従来のWebチャットでは定期的なリロード時間がn秒として、誰かが発言してからそれを受信するまで平均n/2秒の遅延が発生していた。
しかしこの技術を使うことで、誰かが発言すれば次の瞬間全クライアントがその発言を受信することが可能になる。

Cometを用いたリアルタイムWebチャットはLingrが有名だ。
Lingrはチャットルームに"入室"しないと発言ができず、またチャットルームは誰かが作成した誰かの部屋だ。
今回作成するのは2chのような誰もが自由に匿名で書き込みができ、なおかつチャットルームは誰かの所有物ではなくオープンなスペースになる。もちろん個人のプライベートなチャットルームも作成可能にする予定。
これにより"入室"しないと発言できないLingrより敷居は低くなり、より活発な(そして荒れ気味にもなる)チャットプラットホームを実現することができる。使用用途は主に実況系を想定している。


以下感想。

Cometを用いたチャットの中心プログラムはすぐにできたけど、Ajax部分や慣れないTomcatの設定あたりで結構時間がかかったな。相変わらずIEとFirefoxなどブラウザごとにJavascriptの挙動が違うので苦労した。後はいろいろ調べてApacheとtomcatを連携させたと思ったらApacheの方がCometに対応してなくて結局Comet部分は連携できなかったり・・・・。

あとHTTPの仕様的には同じサーバにTCPのコネクションを同時に2本まで接続することを推奨していて、これにより一つのチャットルームに入るだけで2本全部消費してしまうのが結構めんどかったな。
1本は新規メッセージ取得用、もう1本はメッセージ投稿用だ。
このときほかにもう1本コネクションを張っていると、3本目のメッセージ投稿のコネクションを張ることができず、ほかのコネクションが切れるまで待ってしまう。よってメッセージを投稿することができない。
この問題はとりあえずチャットルームごとにドメインを分けることで解決した。

Firefoxはこれで解決したが、なぜかIEはコネクションを解放しないのか使っていないはずのコネクションを持ち続けて新しい接続を繋いでくれない。ちょっとIEでの挙動は調査が必要だ。
TCP Monitorで見るとページを読み込み終わってもTCPセッションが接続したままになることがあるからそれが原因かも。

あと先人の苦労としてLingrでの記事。
梅田サロン中止のお詫び、およびアーキテクチャ変更についての技術詳細レポート
というのがある。やはりちゃんと考えないとスケーラビリティの確保が大変なようだ。
うちのサーバも今のアーキテクチャじゃ対応できないのでそのうち変更しないとなぁ。
まぁ基本の考え方はよくあるDBのレプリケーションのようにマスターと多数のスレーブという構成でいけそうだ。

あと今回は、できる限り応答速度を速めるためにそれぞれの処理を多数のスレッドでのバケツリレーのように処理するようにした。こうしておくと今後のチャットサーバのクラスタ化にも役に立つだろう。
このときマルチスレッドでアクセスするので、データに対する処理にデリケートにならないといけないのだけど、Javaの強力な並行処理用パッケージが非常に助かった。同期がいらずノンブロッキングでスレッドセーフなキューのConcurrentLinkedQueueなんて涙が出るほどすばらしい。同期のいらなくて読み書き可能のCopyOnWriteArrayListも非常にうれしい。簡単にアトミックなカウンタが使えるAtomicLongも地味に助かる。
やっぱマルチスレッドはJavaだなと改めて思った2008年の正月だった。


CometとAjaxでチャットを作れて自分的にはだいぶ満足したが、作成したものはもったいないので世に出した方がよいとの助言を受けて、勢いに任せてドメインまでとってしまった。
とりあえずアニメ系の実況サイトにする予定。なぜアニメ系かというと俺がオタだから。最近は忙しくてアニメ見ることも少なくなって、アニオタというよりコンピュータGeekと言った感じだけど。

ドメインもとったことだしもうちょっと安定性を高めてしっかりしたものにしてみよう。
後は自然言語処理を用いていろいろとおもしろいアイデアがあるのでそれも試してみたいな。


あ、年末に注文していたキーボードは連休明けの8日に届く予定です。今はオンタリオ国際空港で出発待ちらしい。
ちょうどキーボードを必要としていた時期を見事に避けて届きやがります。

今年の正月はTVも見ずにプログラミングしてたので正月感が全くない。
世間的には"あけましておめでとう"なんだよな。ということで今年もよろしくお願いします。

2008年01月その他のエントリー