node.jsでsocket.ioを使ってチャットを作っています。

メッセージはMySQLに保存するようにしてます。

JavaScriptの使用できないガラケーからも投稿できるようにする必要があったので、
ガラケーからの投稿は、テンポラリのMySQLテーブルに保存し、
node.jsのサーバーサイド側で、そのテーブルを1秒ごとにチェックし、
メッセージがあれば、socket.ioに接続しているユーザーにemitするようにしました。

しかし、socket.ioの接続人数や、ガラケーからの投稿数が多くなると、
1秒毎にチェックしている処理が遅延してしまいます。

ガラケーからの投稿をスマートに投稿できる良い方法があれば教えてください。

それではよろしくお願いします。

---------
node.js
v0.6.8

socket.io
0.8.7

Centos
5.7

Apache
2.2.3

MySQL
5.5.20

PHP
5.3.3

回答の条件
  • 1人2回まで
  • 登録:
  • 終了:2012/04/20 15:09:45
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:y-kawaz No.3

回答回数1422ベストアンサー獲得回数226

ポイント100pt

ガラケーからの投稿も同じNodeプロセスで受けてるんでしょうか?であればMySQLを定期チェックするのではなく投稿タイミングでio.socketsにemitしてやれば良いんじゃないですか?

もしくはガラケーは別システム(例えばPHP等)で受けているのであれば、Node側に以下のような受け口APIを作っておいて、PHPからローカルで叩いてやれば定期チェックは不要だと思います。

Node側

//新着メッセージの通知を受ける
app.get("/emitMessage", function(req, res)
  //socket.io接続中のユーザ全員に新着メッセージを配信
  io.sockets.emit("message", getNewMessagesFromMySQL());
});

PHP側

<?php
/* ガラケーからの投稿処理(略) */

//ガラケーから投稿があったことをNodeへも通知
file_get_contents("http://localhost:3000/emitMessage");
id:araishi

ご解答ありがとうございます!
PHPから叩けるならサーバーサイドの定期チェックが不要になりますので助かります。
ちょうどexpressを使っていたんですが、socket関係の処理とexpressのリクエストをさばく処理を混合して書ける事に気づきませんでした。
ファンタスティックです!

2012/04/20 15:06:22

その他の回答2件)

id:windofjuly No.1

回答回数2625ベストアンサー獲得回数1149

ポイント100pt

全体構成を変えない方向で考えてみました・・・。

まず考えたのが、
もしもデータベースエンジンがMyISAMであればInnoDBに替えてみること。
移行作業はもっとも簡単でレンタルサーバーでも問題は無く移行できるはずです。
(別な手段としてSQLite3を併用するということも考えられますが、
 MySQLのような柔軟性はないので微妙で避けたいですね)

効果的(こっちが本命)だと思われるのは、キャッシュにmemcachedを利用すること。
phpからのmemcached利用はかなり簡単になっていますし、
携帯からの入力キャッシュ程度であれば、
メモリが満杯になるような心配も多分ですがないでしょう。
(メモリが心配になるほどのアクセス数だと、
 サーバーのハードウェア増強を考えないといけないでしょうから・・・)
http://php.net/manual/ja/book.memcached.php

id:araishi

ご回答ありがとうございます!
memcachedは使ったことなかったのですが、ガラケーサイトの重いライブラリがあったので、
memcachedを使ってみると早くなった気がします!
PHPからは簡単に使えたんですが、node側から使うのはまた調べる必要がありそうでした。

2012/04/20 15:08:47
id:taroe No.2

回答回数1099ベストアンサー獲得回数132

ポイント100pt

まずはどこがネック担ってるかを調査することです。

1.ソケットの同時接続コネクション数などの制限にひかっかっている
2.DB側の問題


接続人数がどの程度になったときから
遅延が起こるかってことです。

その遅延がどの程度の遅延かというのも重要です。
遅延程度によって、どこがネックになってるかが予想できるからです。


ソケット関係の制限で、
接続数が多くなると待ち状態になってるだけではないか?と
思うのですが・・。

MYSQLがいくら重めと言っても、その程度の検索、更新処理で
大きな遅延が起こるまでには至らないと思いますが。


更新と言ってもINSERTしかないと思いますしね・・。

id:araishi

ご回答ありがとうございます!
ネックになってるところを調べようと、
ソケット接続数をカウントするようにしてみました。
最大同時接続は100人ぐらいでした。

つぎにトラフィックツールのMUNINを見てみるとHDDのIOのグラフが高くなってる時がありました。
IOをあまり使った覚えがなく、VPSだったので他のユーザーの影響を受けているのかもしれないということで
VPSの調査依頼を行うと他のユーザーの影響を受けており、他のユーザーを制限してくれるようになり、
負荷については解决できたと思います!

2012/04/20 15:06:39
id:y-kawaz No.3

回答回数1422ベストアンサー獲得回数226ここでベストアンサー

ポイント100pt

ガラケーからの投稿も同じNodeプロセスで受けてるんでしょうか?であればMySQLを定期チェックするのではなく投稿タイミングでio.socketsにemitしてやれば良いんじゃないですか?

もしくはガラケーは別システム(例えばPHP等)で受けているのであれば、Node側に以下のような受け口APIを作っておいて、PHPからローカルで叩いてやれば定期チェックは不要だと思います。

Node側

//新着メッセージの通知を受ける
app.get("/emitMessage", function(req, res)
  //socket.io接続中のユーザ全員に新着メッセージを配信
  io.sockets.emit("message", getNewMessagesFromMySQL());
});

PHP側

<?php
/* ガラケーからの投稿処理(略) */

//ガラケーから投稿があったことをNodeへも通知
file_get_contents("http://localhost:3000/emitMessage");
id:araishi

ご解答ありがとうございます!
PHPから叩けるならサーバーサイドの定期チェックが不要になりますので助かります。
ちょうどexpressを使っていたんですが、socket関係の処理とexpressのリクエストをさばく処理を混合して書ける事に気づきませんでした。
ファンタスティックです!

2012/04/20 15:06:22

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません