この記事は,日経ソフトウエア2007年1月号,連載「簡単実装で学ぶWeb技術2006」の第7回「Comet――プッシュ型のWebアプリケーションを作る」の再録です。記事は執筆時の情報に基づいており,現在では異なる場合があります。

結城 浩(ゆうき ひろし)
1963年生まれ。仕事&趣味は「プログラム書き&文章書き」。JavaやPerlの入門書で人気の著者。Webサイトはhttp://www.hyuki.com/

 こんにちは,結城浩です。

 今回は,サーバーからデータをプッシュするタイプのWebアプリケーションを作成する技法の「Comet」を紹介します。簡単なチャット・プログラムを通してCometの仕組みを学びましょう。

Cometとは

 通常のWebアプリケーションは,クライアント(Webブラウザ)から送られてくるリクエストを受け取って動作します。つまり,WebアプリケーションはユーザーがWeb上のリンクをたどったり,ボタンを押したりすることをきっかけに動くのです。ここで,動きの主導権はクライアント側にあります。クライアントがサーバーから情報を「引き出す」ことによって動作するので,通常のWebアプリケーションはプル(pull)型と呼ぶことがあります。ユーザーがサーバーの情報を「引き出す」イメージですね。

 ここで紹介するCometは,プル型と逆のプッシュ(push)型のWebアプリケーションを作る技術の一種です。プッシュ型のWebアプリケーションでは,サーバーがクライアント側に情報を「押し込む」動作になるのです。

 …と,これでは話が抽象的なので,Webチャットのアプリケーションを例にとって,アプリケーションを構成するパターンを三つ紹介していきます。現在利用されている技術と,ここで紹介するCometの違いを理解してください。

パターン1●AjaxやCometを利用しない場合

 図1は,AjaxやCometを利用しないシンプルなWebチャットの構成図です*1。ブラウザは,サーバーにアクセスして「現在のチャット・ログ」を取得します。これはクライアント側主導でサーバーから情報を引き出しているので「プル型」です。

図1●ポーリングを行う場合
図1●ポーリングを行う場合

 複数の人が同じサーバーにアクセスしてチャットしている場合,最新のチャット・ログを得るために,ブラウザは定期的にサーバーにアクセスする必要があります。この,「定期的にサーバーにアクセスして最新情報を得る」方法を,ポーリング(polling)と呼びます。

 たしかにこの方法で,チャットをWebアプリケーションとして実装できます。ただし,サーバーの情報が更新されていてもいなくても,ブラウザが定期的にサーバーにアクセスする必要があります。言い換えれば,ユーザーが多くなってくると,サーバーへのアクセス数が非常に多くなってしまいます。

パターン2●Ajaxを利用する場合

 図2はAjaxを使ったWebチャットの構成図です。クライアント側からサーバーへ,2種類のアクセスを行っています。

図2●JavaScriptでポーリングを行う場合
図2●JavaScriptでポーリングを行う場合

 まず,ブラウザからサーバーへアクセスします。このアクセスはチャットを利用する最初の1回だけで,チャットをするページが返されます。これが一つ目のアクセスです。二つ目は,ブラウザからではなくJavaScriptから行われるアクセスです。JavaScriptがサーバーにアクセスし,チャット・ログを表示するために必要な情報を得ます。この情報をJavaScriptで画面に反映します。

 これは,ブラウザの画面の遷移に同期しないで,サーバーのデータを取得して画面を書き換える――いわゆるAjax的なアプローチになります。ただし,クライアント側主導でサーバーから情報を引き出していることはパターン1と変わりません。パターン2もプル型です。

 最新のチャット・ログを画面に表示するためには,図1のときと同じように,JavaScriptは定期的にサーバーにアクセスしなくてはなりません。つまりポーリングを行う必要があるのです。

パターン3●Cometを利用する場合

 図3はCometを使ったWebチャットの構成図です。クライアント側からサーバーへは3種類のアクセスを行っています。

図3●Cometでプッシュする場合
図3●Cometでプッシュする場合

 一つ目は先ほどと同じく,ブラウザからサーバーへのアクセスです。

 二つ目は,「読み込み用のJavaScript」からサーバーへのアクセスです。このアクセスはHTTPを使うのですが,その振る舞いは変わっています。「読み込み用のJavaScript」からのリクエストを受け取ったサーバーは,すぐにはレスポンスを返さないのです。つまり,わざとクライアント側を「待たせて」おきます。クライアント側は「誰かがチャットに書き込む」というイベントを待つのです。

 三つ目のアクセスは,「書き込み用のJavaScript」からサーバーへのアクセスです。このアクセスはユーザーがチャットに対して発言(書き込み)したときに起こります。サーバー側は「書き込み用のJavaScript」からのリクエストを受け取ると,そのことを,待たせておいたスレッドやプロセスに通知します。この通知は「いま書き込みがあったので,チャット・ログが更新されていますよ」という意味になります。

 通知を受けたスレッドやプロセスは,「読み込み用のJavaScript」に対してレスポンスを返します。このレスポンスは,通常のHTTPレスポンスと何も変わりません。しかし,「サーバーに書き込まれたタイミングで返される」わけですから,サーバー主導で,情報がクライアント側に送られてきたと見なすことができます。つまり,これは(疑似的に)プッシュ型の通信を作り上げていることになるのです。

 プッシュ型の通信ではありますが,特殊なソフトウエアを使っているわけではありませんね。「WebブラウザとJavaScript」という既存のソフトウエアだけで動きます。Cometは既存のWebアプリケーション動作環境の範囲内で,プッシュ型のWebアプリケーションを実現していることになります。

 Cometを使ったチャットでは,クライアントは定期的にサーバーへアクセスする必要はありません。つまり,Cometを使うとポーリングは不要になります。「読み込み用のJavaScript」は,サーバーからのレスポンスを受け取った後,再度リクエストを発行します(そして待たされます)。しかしそれはあくまでサーバーに書き込みがあったときだけです。サーバーに更新がないときには,クライアントからサーバーにアクセスは発生しません。

Cometの良い点,悪い点

 前節で見たように,Cometではポーリングが発生しなくなります。したがって,サーバーへのアクセス数を減らすことができます。また,サーバーに書き込みがあったタイミングで情報が送られてくるので,リアルタイム性も向上することになります。これらはCometの良い点です。

 しかし,良い点ばかりでもありません。プッシュ型を実現するため,Cometではアプリケーションの動作中,「読み込み用のJavaScript」とサーバーとつながりっぱなしにしておく必要があります。これは,Cometの悪い点です。なぜなら,つながりっぱなしではサーバーの資源を確保し続けてしまうからです。この問題を解決し,Cometを有効に使うためには,これまでとは異なる要求を満たすWebサーバーが必要になってきます。

この先は会員の登録が必要です。有料会員(月額プラン)は初月無料!

日経 xTECHには有料記事(有料会員向けまたは定期購読者向け)、無料記事(登録会員向け)、フリー記事(誰でも閲覧可能)があります。有料記事でも、登録会員向け配信期間は登録会員への登録が必要な場合があります。有料会員と登録会員に関するFAQはこちら