ページ

2010年11月20日土曜日

WebSocketの紹介記事

WebSocket、名前だけで興味があったのですが、まとまった紹介記事がでていましたのでじっくりと読んでみました。ただ、寄り道が多くて。

第1回 node.jsの衝撃とWebSocketが拓く未来

まずはnode.js (JavaScriptの実行エンジン)の話で寄り道。パラメタとして指定されたJSファイルを実行するもののようですね。実行環境としてTCPサーバ、HTTPサーバ機能を持っているため、JavaScriptで簡単にサーバ(機能)を作成することができるようです。サンプルがでていますが、単純なHTTPサーバ、TCPのエコーバックサーバあたりであれば本当に簡単にかけています。

とりあえず、上の範囲で、「ネットワークサーバをJavaScriptで」というところまではOK。後は「イベント駆動でハイパフォーマンス」のところですね。

こちらについては、サーバを構成するJavaScriptでイベントが使える、というのがポイントのようです。サンプルでは(イベントを使う)setTimeoutを使ったケースと、スレッドをブロックするSleepを使ったケースとで速度比較しています。が、これは解り難いですね。

じっくり読むと、setTimeoutのケースでは、あるHTTPリクエストに対する処理の一部が(この場合はタイマーイベントの)イベントハンドラに渡されていて、イベントによって実行されるようになっています。その一方で、サーバ本体はイベント処理の完了を待つこと無く次のリクエストの処理に入っています。Sleepでは、シーケンシャル実行なのでSleepが完了して残りの処理を終えるまでは次のリクエストの処理に移れない、というところを見せるサンプルになっています。

ノンブロッキング、イベント駆動は、普通の(コンベンショナルな)言語で実装しようとすると死ぬほど面倒になるのですが(ずっと以前にVB2.0でそういうのを書きました)、最近の言語だと簡単でいいですね。実行時の環境がそのままイベント処理に渡されるので、面倒なデータ管理が一切不要になっています。

元々HTTPは、リクエスト/レスポンスをシーケンシャルに処理していくことを前提にしたプロトコルです。各々のリクエスト/レスポンスは独立している(ステートレス)と想定していて、並列性は個別のリクエストの処理の中ではなく、リクエスト受付レベルで担当するようになっていました(httpdレベルでの並列動作)。ところが現在ではHTTPはこのような当初の前提から外れたところで酷使されています。記事で紹介されているチャットなんぞはもろにHTTP想定外の使われ方ですね。本来であれば、専用プロトコルを使うべきシチュエーションなのですが、みなさん、そういうものでも何でも無理やりHTTPで実現しようとする傾向があり、その結果HTTPサーバに無理をいうようになってきているわけです。

と、延々とサーバサイドの話をしてきて、実はこれはWebSocketとは無関係(とまではいいきれませんが)の前置きでした。この記事の著者の説明、いいたいことはわかるのですが、微妙に説明のポイントがずれているような気がします。

WebSocketは、概念的には、プロトコルそのもの(IETF規定だそうで)と、それをクライアントサイドで使うためのAPI(はW3C規定)から構成されているそうです。

APIは随分と単純です(ということはその先が面倒を一手に引き受けているわけですね)。サーバとバインディングする形でWebSocketオブジェクトを作り、接続、切断、受信についてはイベントハンドラで、送信については関数呼び出しの形式で使うようになっています(書いていませんが、エラー処理もイベント扱いでしょうね)。

記事ではnode.jsとWebSocketコードの比較の話がでていますが、両者ともソケット通信をイベント駆動でモデル化している点で似通った構成になっているのでしょう。でも、たしかにこの二つを組み合わせてサーバサイド、クライアントサイドを作るのは見通しがよくなりますね。

Ajax、Comet、WebSocket(Server Push)の比較図、WebSocketだけ塗り潰されているので却って見づらくなっていますが、まあ違いはわかるでしょう。Ajax(Polling)、Comet(Long Polling)はある意味HTTPそのままの使い型であって、そのため、サーバに無理をかけているところがあります。これに対してWebSocketは、概念的にはもうHTTPではないですね。むしろTCPベースのサーバの概念を無理やりHTTP上に持ってきたものといえるでしょう。ですが、逆にコード的には無理のないきれいな実装が可能になります(というか汚いところがすべて隠蔽されているわけですが)。

WikiPedia WebSocket
W3C WebSocket API こちらもまだドラフト。シンプルですね。
IETF WebSocket Protocol まだI-Dです。おもしろいプロトコルです。

これが広まるとTCPベースのサーバ消えてしまいそうな気がします。

第2回 WebSocketの現状と技術的課題

続編。こちらは標準化の状況と課題の話です。まあ標準化され、どこでも使えるようになるにはまだかかりますよ、ということで。そういえばJS自体だってどのブラウザでもそこそこ安定して動作するようになるまでにどれだけかかったことか。というか、未だにJSを止めないとマシンに負荷がかかってどうしょうもなくなるサイトが多数あるわけですか。

で、プロトコルメッセージ例が出ていますが、ヘッダとボディの間は1行空けておきましょうね。要らぬ誤解を招きます。

個人ドラフトからWGドラフトへの切り替わりで互換性が失われたとのことですが、そのああたりはセキュリティ周りの要請のようです。今時の実用プロトコルとしてはそのあたりに充分留意しなければいけないのでしょう。今後はこのレベルの大修正は無いのではないですかね。

ブラウザーサポートについては、新しいものは順次サポートされて行くのでしょうが、問題は(いままでにもありましたが)古いブラウザを使い続ける人の存在ですよね。こればかりはしょうがないですが。まあ、逆にWebSocketが古いブラウザを捨てるいい切っ掛けになるかも知れません。

WebSocketはステートフルサーバなのでスケール問題が出てきます。記事ではHTTPサーバなら単純に、とか書いていますが、今のHTTPサーバはそんなに単純ではないはずで、ロードバランサーなんかもセッションベースで動作してたりするわけですから、WebSocketが広まれば(技術的には同レベルなので)それなりの対策が取られることでしょう。もうひとつ挙げられているブロードキャスト問題はWebSocket限定ですね。まあ、このあたりも含めてスケーラブルWebSocketといったものが開発課題にになってくることでしょう。

次はNew Bamboo's Pusherの話。WebSocketへのruby wrapperだそうです。WebSocket APIまでは標準化されるので、そのレイヤーで書いたほうが移植性がありそうなものですが、やはり面倒なんでしょうか?イベントハンドラは確かに書きやすそうです。onmessgeでの集中処理って実際面倒ですからね。rubyだけでなく多数の言語バインディングがあるのですね。有名処は網羅されています。

既存のメッセージングプロトコルのWebSocket対応状況。メッセージングプロトコル(XMPP等)がWebSocketに対応してくれると、ブラウザUIで使えるようになるわけですね。WebSocketが広まってくると(対応ブラウザが増えてくると)既存プロトコルのWebSocket化が流行るのかもしれません。次の記事で紹介されているnoVNCなんかもその類ですね。

第3回 WebSocketでWebは変わる? 大胆予想!

最終回ということで使われている例が挙げられています。最初はNoVNC、HTML5(Canvas)とWebSocketで実装した(というかしてしまった、といいたいですね)VNCクライアントです。ちょっと前に他のところで紹介記事を見て、実装方針とかを読んだのですが、まあよくやる、といったものでした。VNCプロトコルデータをHTTP上でエンコードして送受信しているようです。

さてこういう実装例が出てくるといつもの(恒例の)綱引きがはじまります。例えばVNCの場合、JavaViewerがあれば、クライアントのブラウザ上で任意のGUIアプリケーションを、そこそこ高速/リアルタイムに表示させることができます。JavaViewerで同じことができるのにあえてWebSocket化するのはどういう理由なのでしょう?

VNCのJavaViewerはRIAに対するある意味究極の回答になっています。それこそ任意のGUIプログラムをそのままで使うことができるわけですから。ですが、時代に流れ的にはWEBアプリ化の方が主流ですよね。まあ、新しいGUIプログラムを作るよりWEBアプリを作る方が簡単、というのがあるのかも知れません。しかし、WebSocketを使うようなWEBアプリになった場合に、はたして「簡単」になるんでしょうか?旧来のHTTPベースのWEBアプリは確かに簡単でした(細かなUI制御を捨てれば)。しかし、凝ったUIを欲しがった場合、WEBアプリとネイティブアプリ(をブラウザ上で操作)とどちらが簡単になるんでしょうね。このあたりの流れの行き着く先がどうなるかは非常に興味深いところです。

0 件のコメント:

コメントを投稿