ブラウザ間双方向通信(P2Pモデル)アプリケーションを作ってみた

デモが稼働しているか

12/24 19:43 現在 judge2だけ稼働中

何を作ったの?

ブラウザ上でP2Pを行ってチャットのようなものをするデモアプリケーションを作ってみました。

デモの前に

いきなりですが、このチャットアプリケーションを動かす為にはちょっとした設定が必要です。


次のページを参考にして、java.policyファイルを編集してみてください。

http://d.hatena.ne.jp/ranha/20081219/1229669626
http://ranha.kerox.info/HowToEditJavaPolicy.html


HowToEditJavaPolicyをほどほどに読んで設定してください。
重要な所は、"この設定では何をしているの??"に書かれています。セキュリティに関する所ですので、良く読んでください。
編集してデモを行った後は、編集した部分を消しておいてください。

次に、java.policyがきちんと編集出来たかどうかを調べる為に次のページにアクセスしてみてください。

http://ranha.kerox.info/judge/judge2.html

これはcross-domain通信を行うので、java.policyが設定されていない場合は動きません。
更に、WindowsXP,Mac Leopard,Ubuntu上のFirefox3.0.xでの稼働を確認しています。


なお、開発にはMac LeopardとFirefox3.0.xしか利用しておりません。
IESafariOperaChromeをお使いの方はFirefoxを使ってください。

気を取り直して

何を作ったのか、でしたね。

数日前からこのブログでは、ブラウザ上で双方向通信を行う話をしてきました。
双方向通信が行えると、世に言うP2Pアプリケーションと言った物が作れる様に成ります。

作れる様に成ります、だけではどうも真実味が無いので実際に作ってみる事にしました。
まずはデモページにアクセスして、存分に使ってみてください。(といっても、単なるチャットなんですが・・・。)


http://ranha.kerox.info/udphp/chat.html
UDP版です。
UDP版は、Twitterからステートを抜き去ったような、自分が存在している時間の全体の発言しか見えないアプリケーションになっています。
非常に適当なので、ちゃんと他のブラウザとコネクションが張れたかどうかは分かりませんので、人間SYN-ACKをやる必要があります。


JavaAppletを使用しているので、少々立ち上がりが遅いかも知れません。
その点はご了承ください。

それと、WindowsXPMac LeopardUbuntu上でFirefoxを使っていても動かない環境があると思います。
これは、今回NAPTを超える為に使った手法(Hole Punchingです)に依存しているからです。


少なくとも、上記のjudge2.htmlにアクセスしてSymmetricが出たルータだと、正常にconnectionを張るのが大変難しく成ってきます。


さて、何を作ったのか・・・でしたねw

その前に、ブラウザ上でP2Pを行うという事に対して少し

ブラウザ上でP2P?

ブラウザ上でP2Pを行える様に成った、と聞いてピンと来る人は少ないと思います。
ただ、ピンと来ないという事が逆に重要で在るとも思うのです。

昨今、Webアプリケーションが増えてきました。それらはやはりWebブラウザをプラットフォームとして動かします。従来デスクトップアプリケーションでやっていた様な事も、ブラウザが肩代わりしているようにも見えます。
そんな中、Webブラウザ上でP2Pが行えるように成る・・・、というのは別段突拍子のある話では無いと思うのです。

むしろ、エンドユーザもネットワークにアクセスしてくるようになりました。その時に使われるのはやはりWebブラウザなのです。
なのでブラウザ上でP2Pが使えるようになるというのは、ユーザ数の意味でもそれなりに嬉しいのですね。

じゃあブラウザ上でP2Pを出来ると何が嬉しいの??

それはズバリ、P2Pアプリケーションによるメリットが何か、と問う事と同じになるでしょう。

具体例から行きましょう。

局所的な負荷を分散する事が出来る

サーバを立てていて、局所的なトラフィックに喘いでいて、「なんでサービスを享受するのはユーザなのに、サーバサイドでこんなに何もかも頑張らないといけないんだ・・・??」と感じた方はいらっしゃるのでは無いでしょうか?


最も典型的な動画ストリーミングサービスを例にしてみましょう。

ユーザがまずアクセスして来ます。次に、サーバが全ユーザに対してストリーミングで動画をマルチキャストします。
この時、サーバ側に発生する負荷はかなり大きく成る事が想像出来るでしょう。
使用ユーザが少ないうちは済むと思うのですが、増えて行くにつれて、普通の回線では対応出来ない様に成ってきます。


ではここで、ブラウザ上でのP2Pを行えるとどうなるでしょうか?
あるブラウザが、あるブラウザに対して動画をストリーミングで送る・・・。

このモデルだと、サーバに対する局所的負荷が、ネットワーク全体に分散する事に成ります。そういう意味での局所的な負荷分散という事なのです。

ブラウザ上で分散システムを作る事が出来る

昨今はJavaScriptのお陰で、クライアントサイドでプログラムを動かすというモデルが割と当たり前に成ってきました。
Googleは先日、Native Clientというブラウザで(厳密にはブラウザのプラグインという形でですが)プラットフォームネイティブなコードを実行出来るシステムを作りました。


これは、クライアントサイドでより効率的にコードを実行させる仕組みだと言えるでしょう。実際にブラウザの上でゲームも動いているようですね!


さて、という事は、ブラウザ上で分散システムを作るという条件が揃ったと思われます。


これに関しては具体例を出すのは難しいですが・・・、敢えて言うなら、普通のアプリケーションとして稼働している分散システムの一部が、同様にブラウザ上で動く様に成る、と言える程度でしょう・・・。


ただ、これは多くの開発者に取っても、ユーザに取ってもメリットは感じ辛いと思います。そもそも私も説明しづらいですし・・・。
ブラウザ上に載せるメリットというのは、エンドユーザが簡単に使える様に成りますよ、という事だとは思いますね。


ページにアクセスした瞬間、実は分散システムに参加していたんだぜ!!っていうような感じですね。それは割と理想的なんでは無いかと個人的には思います。

今回作ったのはどっち?

負荷分散のタイプです。


どんな所で負荷分散しているのかについて述べます。


従来のWebチャット(クライアント・サーバモデル)では、ユーザがした発言は一度サーバに送られていました。
次に、サーバからブラウザが発言を受け取る(polling)か、サーバがブラウザに発言を送るか(push)するかでしたね。

最近だと、pollingの方はAjax・・・pushの方はCometという形でも見直される様に成ってきました。Cometの方はHTTPならではの問題もあり、まだ広く上手く行っている方法は無いようですが。(HTTPだから使えるんだよ、という話も有るかも知れませんね。ブラウザでTCPやれば良いじゃん!ていう簡単な話にも成りにくいと思います。)


今回は、ユーザがした発言は一度サーバに送られる事無く、ユーザからユーザに直接発言を送る形に成っています。
どう送っているのか・・・は気になる所だと思います。


要するに、ネットワークトポロジ、オーバーレイネットワークトポロジはどんな感じになっているの??という事ですね。


今回はフルメッシュにしています。ですから、自分とchat-roomにいる人全員にconnectionが張られていると考えてください。
なので、自分がした発言はまさに直接相手ブラウザに送られます。相手からの発言も、直接ブラウザにやってくるわけです。
ですから・・・と言ってはなんですが、メッセージングを本当にブラウザ間で行っていて、サーバ側で保存しない実装にしましたので、chat-roomに入った時にそれまでの(自分が居なかった時間の)logを見る事は出来ません。


今回の実装では、サーバは負荷を免れています。が、ネットワーク上に存在するセッションの数は、従来のクライアント・サーバモデルよりも増えています。
(余談ですが、P2Pを使うと局所的な負荷を分散する事は出来るが、結果的にネットワーク全体のトラフィック数は増えるという話とも関係してきます。)


グラフィカルな差異を、図を使っても示してみたのでそれを挙げておきます。
こちらの方が分かり易いと思いますのでw(使い回しですが。)

実装の詳細について

少なくとも、ページのソースを見てもらえればJavaScript側の全ソースは見えると思います。うざったく感じるかもしれませんが、少々コメントを振っているので読んでもらえれば光栄です。


Java側では、基本的に雑多な部分を隠蔽しています。
あんまり読みたい人も居ないのでは無いと思うのですが、もしかしたらとも思いますので、適当なコードホスティングサービスに投げるつもりでいます。(SourceForgegithub、launchpadあたりかと考えているのですが。)


NAPT越えについては、
ちょっとNAPT超えてみようぜ! - Yet Another Ranha
こんな記事(というかスライドなのですがw)をつい先日挙げたので、取りあえずの参考にしてもらえると良いのでは無いかと思います。

実装してみて

ブラウザ間通信だけでWebアプリケーションを作るのは難しいでしょう。従来のクライアントサーバモデルと組合せるべきです。


一番先に台頭してくるのは、やはり「局所的な負荷を分散」させる方向だと思います。「サーバがクライアントに投げるデータがでかい」時でしょうか。


例えば、ニコニコ動画の新着ランキングであれば、割と近いタイミングである1つの動画にアクセスする人数は多いと思います。
その時、手抜きで実装するならば、一番最近サーバが動画を送ったホストから、別のホストに動画を送らせる・・・と言った事は十分可能だと思います。まぁ途中でそのホストが落ちたらどうするかなどという別の問題が発生してくるわけですが、そこんとこは割とどうとでも成ります。最悪、サーバに頼れば良いので。


私としては、広域な分散にはちと疲れてしまいましたw まだ何もやれていなくてNAPT Traversalばっかりなんですがw(あと ブラウザ上で色々やる所から来るバッドノウハウの習得とか)
ですので、しばらくはサーバサイドというか自分がリソースを把握している状況下での分散システム開発/分散プログラングを楽しもうと思っています。
広域分散をやるには、Router(NAPT)に明るい、NAPT Traversalがやりたくて仕方が無い様な人間と組むと楽しいと思います。


後はどうやって実装するか・・・という話でしょうか?
ActionScript(+ JS)、Java+JavaFX(+ JS)、ブラウザプラグイン(+ JS)など様々な形があると思います。是非ともお好きな手法で楽しんでみてください。
今回私がやったのは、Java + JSによるP2PonBrowserです。
どれが優れているかは分かりませんが、ちょうどサーバが過負荷で困っていたんだ、という方は、是非ともブラウザ間双方向通信で何か実装してみてください。