[NodeJS] nodeで例外処理を書いて、最低限落ちないサーバー実装を行うException Handler
こんにちは、@yoheiMuneです。
最近、node.jsを使ってサーバー運用を始めてみました。
初めてのことが多くて大変ですが、その分学んだこともたくさんあるので、ブログにドシドシとアウトプットしたいと思います。
例えば、以下のようなサーバーコードがあったとして、エラー部分が実行されるとサーバーは応答しなくなります。
通常「関数の未定義」みたいな初歩的なエラーはテストで発見できます。 しかし「予期せぬ入力値」などはテストケースから漏れることもあり、またエラーケースに対する実装が十分でないこともあるので、 運用中にも予期せぬエラーが発生することはぜひ想定すべきです。
Apacheなどのサーバーを利用していたり、フレームワーク(strutsやSpringとか)を使っている場合には、 こーゆうエラーもいい感じに処理してくれるのですが、node.jsでサーバーを実装するともちろんしてくれないので、大変ですねー。
エラーが発生するかもという箇所は、ちゃんとエラーハンドリングを個別に書くのがベストです。
最後までご覧頂きましてありがとうございました。
最近、node.jsを使ってサーバー運用を始めてみました。
初めてのことが多くて大変ですが、その分学んだこともたくさんあるので、ブログにドシドシとアウトプットしたいと思います。
node.jsでは1つのエラーでサーバーダウン。。
今まで最終的なエラーハンドリングは、ApacheやらSpringやらstrutsやらに任せてきた自分としては、node.jsは斬新です。 1つのJSエラーが発生するとサーバーが停止してしまいます。例えば、以下のようなサーバーコードがあったとして、エラー部分が実行されるとサーバーは応答しなくなります。
// 必要なモジュールを読み込みます。 var http = require("http"); var fs = require("fs"); var server = http.createServer(function (req, res) { res.writeHead(200, {"Content-Type":"text/html"}); var output = fs.readFileSync("./index.html", "utf-8"); res.end(output); }); server.listen(8080); undefinedFunction(); // 定義していない関数の呼び出しでエラー!!!上記の場合、例えば以下のようなエラーが表示されて、サーバーは停止します。
$ node app.js /Users/munesadayohei/tmp/app.js:13 undefinedFunction(); // 定義していない関数の呼び出しでエラー!!! ^ ReferenceError: undefinedFunction is not defined at Object.<anonymous> (/Users/munesadayohei/tmp/app.js:13:1) at Module._compile (module.js:456:26) at Object.Module._extensions..js (module.js:474:10) at Module.load (module.js:356:32) at Function.Module._load (module.js:312:12) at Function.Module.runMain (module.js:497:10) at startup (node.js:119:16) at node.js:901:3また、以下のように、「/」にアクセスした時に実行されるメソッドに不備があり、サーバーが停止することもあります。
// 必要なモジュールを読み込みます。 var http = require("http"); var fs = require("fs"); var server = http.createServer(function (req, res) { res.writeHead(200, {"Content-Type":"text/html"}); var output = fs.readFileSync("./index.html", "utf-8"); // JSONパースができずエラー var json = JSON.parse('<tag>NOT JSON FORMART</tag>'); res.end(output); }); server.listen(8080);「/」にアクセスすると、以下のようなエラーが発生して、サーバーは停止します。
$ node app.js undefined:1 <tag>NOT JSON FORMART</tag> ^ SyntaxError: Unexpected token < at Object.parse (native) at Server.<anonymous> (/Users/munesadayohei/tmp/app.js:10:18) at Server.EventEmitter.emit (events.js:98:17) at HTTPParser.parser.onIncoming (http.js:2027:12) at HTTPParser.parserOnHeadersComplete [as onHeadersComplete] (http.js:119:23) at Socket.socket.ondata (http.js:1917:22) at TCP.onread (net.js:510:27)と、こんな感じでnode.jsを利用すると、1つのエラーがサーバーが停止してしまうので、なかなかスリリングです。
通常「関数の未定義」みたいな初歩的なエラーはテストで発見できます。 しかし「予期せぬ入力値」などはテストケースから漏れることもあり、またエラーケースに対する実装が十分でないこともあるので、 運用中にも予期せぬエラーが発生することはぜひ想定すべきです。
Apacheなどのサーバーを利用していたり、フレームワーク(strutsやSpringとか)を使っている場合には、 こーゆうエラーもいい感じに処理してくれるのですが、node.jsでサーバーを実装するともちろんしてくれないので、大変ですねー。
node.jsでとりあえず落ちないサーバーを作る
とりあえず落ちないようにするために、Exception Handlerを実装します。 node.jsのネイティブでサポートしている仕組みで、サーバー実装の最初の方に以下ように記載します。// 必要なモジュールを読み込みます。 var http = require("http"); var fs = require("fs"); // ★★ここがポイントです★★ // サーバー実装の前に、エラーハンドリングを記載します。 process.on('uncaughtException', function(err) { console.log(err); }); var server = http.createServer(function (req, res) { res.writeHead(200, {"Content-Type":"text/html"}); var output = fs.readFileSync("./index.html", "utf-8"); // 以下のエラーが発生しても、とりあえずサーバーは生き残ります。 // JSONパースができずエラー // var json = JSON.parse('<tag>NOT JSON FORMART</tag>'); res.end(output); }); server.listen(8080); // ここのエラーでも生き残ります。 // undefinedFunction();上記のようにuncaughtExceptionイベントを実装することで、エラーが発生してもそのメソッド内で対応して、サーバーが落ちないようにできます。 ただ、uncaughtExceptionでキャッチした場合には、どのリクエストのものかは分からないので、エラーレスポンスを返すことはできません。
エラーが発生するかもという箇所は、ちゃんとエラーハンドリングを個別に書くのがベストです。
// ちゃんとエラー処理を書く try { var json = JSON.parse('<tag>NOT JSON FORMART</tag>'); } catch (e) { res.writeHead(400, {"Content-Type":"text/html"}); res.end('invalid format'); return; }
最後に
node.jsを使って初めて本格的なサーバー運用を行ってますが、こんな基本的なことからいっぱい学ぶ今日この頃です。 node.jsはまだまだ楽しみなところが多くていいですね。今後もノウハウをブログに書きたいと思います。最後までご覧頂きましてありがとうございました。