QA@IT

node.js で大規模チャットサーバーの実装はできますか?(向いていますか?)

9861 PV

はじめまして、質問させて頂きます。

私は今、node.jsでfacebookのチャットのようなシステムを構築できないかと考えています。
必要な機能としましては、
・ユーザーはブラウザでチャットが出来る。(HTML5のWebsocketで実装)
・1対1のメッセージ送受信だけでなく、グループチャットも可
・リアルタイムチャット
・サーバーにログを残す
というイメージです。

チャットサーバーにチャンネル数が一定に定まっており、空いている部屋を利用するイメージではなく、
1ユーザーが送信したメッセージを元にサーバーが処理し、適切な宛先にメッセージを届けるというイメージです。
(ゲームで言うと、MOゲームよりかはMMOゲームに近いイメージ?)
ユーザー数の見積もりは現状ではないのですが、数に縛られない実装にしたいと考えています

このような比較的大規模なチャットサーバーを実装することに、node.jsを使用することはは向きか不向きか、そもそも不可能か、
メリット・デメリットなどの理由をつけてご意見を頂きたいです。

私自身node.jsやネットワークに関して勉強不足な部分があるので、非常に的はずれな質問をしているかもしれません。
的はずれな場合、「ココ、何を言っているかわからないよ」ということも指摘していただければ幸いです。

回答

http://lingr.com/ というチャットサービスを作っている者です。

基本的に、あまりアクティビティの多くない(CPUをあまり使わない)コネクションを大量に扱う目的には、原理的にnode.jsはぴったりだと思います。

実際、Lingrでは、通常のweb部分にはRailsを使い、チャット用のプッシュを行うバックチャンネルをEventMachineというnode.jsと同じリアクターモデルで動作するRuby用のサーバで書いています(正確にいうとthin + async_sinatraです)。ブラウザの互換性を重視して現在もWebSocketsではなくComet/Long-pollで動作していますが、原理的な性能特性はどちらも同じです。

EventMachineもnode.jsも、ちゃんとFDの設定をすれば単体で10,000以上の同時接続をさばけるので、長期的に見てユーザ数が100万でデイリーアクティブ率が10%で平均滞在時間が144分だとして、保守的にみてもプロセス1個で足りるので、ほとんどの内部状態をグローバル変数で持たせることができ(シングルスレッド動作なのでハッシュのmutate atomicityなどを心配する必要もない)、非常に見通しの良いコードを書くことができます。

ただし、ある程度の規模になってくると、問題はバックエンド側になってきます。とくに「サーバーにログを残す」とあるので、おそらく間違いなくボトルネックはDBになってきます。いくら非同期で書けるといっても、DBへのコネクションは有限ですから、どんどん投げっぱなしにすれば良いというものではありません。それに、ルームではなくN:Nの関係性とのことなので、DBへの負担はO(N^2)で大きくなっていくでしょう。

結果的にLingrでは、バックチャンネルを維持する部分だけリアクターサーバを使い、それ以外の95%の部分では通常のWebアプリ(Rails)を普通のブロッキングスタイルで書くことで、メンテナンス性を維持しています。

全部をnode.jsで書くことにすると、たぶん大部分のコードは非同期のコールバックがネストしたメンテしにくい状態になるか、それを避けるためにcoroutine的にコールバックを直列で書けるライブラリに頼って使えるライブラリの選択肢を減らす(EventMachineでいうところのem-synchrony)か、という究極の選択になってくるので、あまりおすすめはできません。が、チャレンジしてみていい解決方法があれば教えて欲しい気もします。w

つらつらと書いてみましたが、おおむねnode.js向きであることは間違いないと思いますので、まずは始められたらよいのではなかと思います。

頑張ってください!

編集 履歴 (0)
  • 非常に早く、なおかつきめ細かな解答ありがとうございます!
    解答を元に、一日色々ぐぐって、サンプルコードの理解ができたので、実装できそうな気がします。
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。