node.jsのチャットサービスのプロセスが落ちる原因が特定できません。


node.jsとsocket.ioでチャットを運営しています。
1日に2~3回nodeのプロセスが落ちてるのですが、原因が特定できず解决できません。

現在は、毎分cronでnodeのport(3001)にアクセスできるか調べて、
アクセスできなければ落ちていると判断し、下記のコマンドを実行して立ち上げています。

node app.js > node_(日付).log /dev/null &

何かエラーでプロセスが落ちた場合には、ログファイルに書き出されるかと思いましたが、
node_(日付).logの中身は
[36minfo -[39m socket.io started
だけしか残っていません。

nodeのプロセスが落ちる理由の特定方法や、
可能性のある原因があれば教えて下さい。

環境は以下の通りです。
-------------------------------
node.js v0.6.8
socket.io 0.8.7
socketの最大同時接続数 約200人
Centos 5.7

よろしくお願いします。

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

ベストアンサー

id:y-kawaz No.1

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

ポイント100pt

まず、起動の仕方に問題があります。それだと標準出力は保存されますが標準エラー出力は保存されません。以下のように起動したほうが良いです。

node app.js > node_(日付).log 2>&1 &


キャッチされない例外が発生したときは process のuncaughtExceptionで捕まえられます。
ここでログを吐くようにするとなにか原因がわかるかもしれません。
また、uncaughtException で例外を補足しても再度throwしなければプロセスは動き続けてくれるので根本解決ではありませんが勝手に落ちるのを防げるケースもあります。

process.on('uncaughtException', function (err) {
    console.log('uncaughtException => ' + err);
});


あとは後は何もログを残さず終了するとのことなので、SWAPがない環境などではメモリ不足によってカーネルに殺された可能性もあるかもしれません。


後ありがちなのが1プロセスがオープンできるファイル数(TCP接続数なども含む)の上限に達してる可能性もあります。ulimit -n で上限の数字を確認できます。
もしこの上限に引っかかっている場合は、rootでしか出来ませんが ulimit -n 999999 などと実行しておくと上限の数字を増やすことが出来ます。コレを実行した後に、もう一度ulimit -nすると999999に上がっていることが確認できるでしょう。

id:araishi

ご回答ありがとうございます。

オープンできるファイル数が5000だったので、ulimit -n 999999として増やしました。
まずこの時点で修正できているか確認するためnodeを再起動してみましたが、9時間後にプロセスが落ちていました。


app.jsにuncaughtExceptionの処理を追記し、
process.on('uncaughtException', function (err) {
console.log('uncaughtException => ' + err);
});

起動するコマンドを下記に変更しました。
node app.js > node_(日付).log 2>&1 &

しばらく様子を見ていると、ログファイルに
uncaughtException => TypeError: Cannot read property 'address' of undefined
と数行出力されていました。

ただその時にチャットのページが表示されなく(404ではなく白紙のページが出力されるような感じに)なってしまいましたので、
現在はuncaughtExceptionの処理を削除し様子を見ているところです。

2012/04/26 17:43:17
id:araishi

プロセスが落ちる原因は、
TypeError: Cannot read property 'address' of undefined
というエラーで、下記の部分が問題だったようです。

io.sockets.on('connection', function(socket) {
console.log(socket.handshake.address.address);
})

socket.handshake.address.addressが未定義になる理由はまだわかっていませんが、原因の特定できたのでこの質問は終了いたします。ありがとうございました。

2012/04/29 02:25:59

その他の回答2件)

id:y-kawaz No.1

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

ポイント100pt

まず、起動の仕方に問題があります。それだと標準出力は保存されますが標準エラー出力は保存されません。以下のように起動したほうが良いです。

node app.js > node_(日付).log 2>&1 &


キャッチされない例外が発生したときは process のuncaughtExceptionで捕まえられます。
ここでログを吐くようにするとなにか原因がわかるかもしれません。
また、uncaughtException で例外を補足しても再度throwしなければプロセスは動き続けてくれるので根本解決ではありませんが勝手に落ちるのを防げるケースもあります。

process.on('uncaughtException', function (err) {
    console.log('uncaughtException => ' + err);
});


あとは後は何もログを残さず終了するとのことなので、SWAPがない環境などではメモリ不足によってカーネルに殺された可能性もあるかもしれません。


後ありがちなのが1プロセスがオープンできるファイル数(TCP接続数なども含む)の上限に達してる可能性もあります。ulimit -n で上限の数字を確認できます。
もしこの上限に引っかかっている場合は、rootでしか出来ませんが ulimit -n 999999 などと実行しておくと上限の数字を増やすことが出来ます。コレを実行した後に、もう一度ulimit -nすると999999に上がっていることが確認できるでしょう。

id:araishi

ご回答ありがとうございます。

オープンできるファイル数が5000だったので、ulimit -n 999999として増やしました。
まずこの時点で修正できているか確認するためnodeを再起動してみましたが、9時間後にプロセスが落ちていました。


app.jsにuncaughtExceptionの処理を追記し、
process.on('uncaughtException', function (err) {
console.log('uncaughtException => ' + err);
});

起動するコマンドを下記に変更しました。
node app.js > node_(日付).log 2>&1 &

しばらく様子を見ていると、ログファイルに
uncaughtException => TypeError: Cannot read property 'address' of undefined
と数行出力されていました。

ただその時にチャットのページが表示されなく(404ではなく白紙のページが出力されるような感じに)なってしまいましたので、
現在はuncaughtExceptionの処理を削除し様子を見ているところです。

2012/04/26 17:43:17
id:araishi

プロセスが落ちる原因は、
TypeError: Cannot read property 'address' of undefined
というエラーで、下記の部分が問題だったようです。

io.sockets.on('connection', function(socket) {
console.log(socket.handshake.address.address);
})

socket.handshake.address.addressが未定義になる理由はまだわかっていませんが、原因の特定できたのでこの質問は終了いたします。ありがとうございました。

2012/04/29 02:25:59
id:taroe No.2

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

ポイント100pt

メモリーの使用量を確認してみては?
メモリー不足になると、落ちそうな気がします。

もしかすると、メモリ-リークしてるとか。

他2件のコメントを見る
id:araishi

ご回答ありがとうございます。
topコマンドもよくわかってなかったみたいではずかしいです。

ulimit -aを実行してみました。

core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 69632
max locked memory (kbytes, -l) 32
max memory size (kbytes, -m) unlimited
open files (-n) 999999
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 69632
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited

2012/04/26 19:13:37
id:a-kuma3

そうやって、みんな大きくなっていくんだって =)

2012/04/26 19:26:40
id:a-kuma3 No.3

回答回数4974ベストアンサー獲得回数2154

ポイント100pt

y-kawaz さんが書かれているように、標準エラー出力を見れば、多分、解決のような気がします。

もし、Node.js が正しく例外処理ができなくて、javascript の例外が出ずに、ズドンと落ちているような場合には、
strace を取っておくと、解決の手がかりになるかもしれません。

strace は、システムコールの何を呼んだか、とか、どんなシグナルが発生したか、ということが分かります。

% strace -p プロセスID

かなり、ずらずらと出力されるので、何かのファイルにリダイレクトしておくと良いかも。
指定したプロセスID のプロセスがいなくなると、シェルに制御が戻ります。

プロセスID は、アンパサンドをつけて Node.js を起動したときの、ログインシェルの標準出力に表示されますが、もし、自動で再起動してるから、よく分からない、ということであれば、
ps の出力から探すか、lsof で該当のポートをつかんでいるプロセスを探します。

% lsof -i:3001


メモリリークを起こしているかどうかは、ps の出力を随時、確認するか、top で見ていれば分かります。

他1件のコメントを見る
id:a-kuma3

C言語を知ってると、プログラムで呼びだしてるシステムコールのままなんですけど、それより上位のレベルで見ると、よく分かんないですよね。

ネットワークのサーバサイドのプログラムなので、

  1. 待って (wait)、
  2. 読んで (read)、
  3. 書いて (write)

の繰り返しです。
その間に、時刻を取る処理とか、プロセス間の同期を取る処理が割りこんでます。

タイムスタンプをつける -tt とか、strace のオプションに入れときゃ良かったですね(すんません)。
http://www.netadmintools.com/html/1strace.man.html

2012/04/26 17:57:39
id:araishi

ご回答ありがとうございます。
はてなで質問していると次々とわからないことがでてきて、
自分の未熟さがわかります。精進します。

2012/04/26 19:04:04

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

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

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

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

回答リクエストを送信したユーザーはいません
${title} {{if price }}
${price}円
{{/if}}