チャットなどのリアルタイムWebアプリケーション開発に使える、
Go言語のcometライブラリを作りました
https://github.com/intelfike/comet
cometについて
なにそれ
ブラウザからのAjaxの通信をサーバー側で止めて、特定のイベントが発生したらレスポンスを返すという手法です。
何ができるの
簡単に言うと、websocketみたいなことが出来ます。
普通サーバーが能動的に通信をすることは出来できないですが、cometを使えばあたかもサーバーから通信をしているような挙動を取れます。
通常のリクエスト
クライアント: 能動的
サーバ : 受動的
comet
クライアント: 受動的
サーバ : 能動的
作ったライブラリの説明
作った理由(現状の問題点)
レンタルサーバーだとポートが制限されていてwebsocketが使えないことがある
結構大きい理由です。
80番ポートしか開いていないとか。
自宅サーバーにするにしても、開放するポートが増えるとセキュリティの問題とか、ポート管理のコストの問題とかがあります。
Goのhttpパッケージの並列処理の挙動がCGIと比べるとイメージしにくい
矢印はスレッドです。Goでは関数は並列化されているものの、同じ関数が複数同時に呼び出される場合は並列化されません。
これを同期するためには、全てのクライアントを認識する必要があります。つまりcookieによりセッション機能を実装する必要があります。
セッション間で情報を共有できない
Goの一般的なセッション管理パッケージは、ユーザー間でデータを共有することについてサポートをしていないっぽいです。(自分が試した範囲では)
Webアプリケーションを作るたびに独自の(情報の共有が可能な)セッションを実装するのは現実的でない
毎度実装していたらミスも増えますし、コストもかかります。
セッションへの理解が浅い人なら実装すら出来ません。
どんなパッケージ?
先ほど挙げた問題を解決するパッケージです。
cometをCGI並に簡単に実装できるようにすることを目指しました。
使い方
チャットのサンプルです。
https://github.com/intelfike/comet/blob/master/example/main.go
セッションを定義
var cmt = comet.NewComet("realtimesession")
引数はセッションを保存するためのcookieのキーです。
重複を避ければ何でも良いです。
セッションを開始
cmt.Start(w, r)
w, rはよくあるhttp.ResponseWriteと*http.Requestの組み合わせです。
Webアプリケーションのページにアクセスがあった時点で、セッションが既にある場合でもできるだけ呼び出してください。
待機
i := cmt.Wait(r)
待機します。Done系統の関数呼び出しで解除され、戻り値としてDone系統の引数が渡されます。
待機を終了
cmt.DoneAll(i)
全ての待機を終了してWaitにデータを渡します。
他にも、自身のみ待機を終了するDone(r, i)
、自身以外の待機を終了するDoneOther(r, i)
があります。
セッションの終了
cmt.End(r)
セッションを終了し、Wait()を終了したり、Done系統の送信対象から外したりといった処理をします。
Webアプリケーションのページから抜けるときに呼び出してください。(呼び出さなくてもある程度は正常に動きますが...)
作った感想
設計した通りの理想的な出来上がりどころか、理想を超えて良い出来になりました。
ひとまずは満足です。
備考
一応まだ試作段階なので互換性は失われやすいです。
現在ver1.0として、互換性が消えたらver2.0に上がります。そうなれば新しいリポジトリを作りますのでver1.0は継続してご利用頂けます。
あと、バグや要望とかあればissueに投げてくださると嬉しいばかりです。