Node.jsでキャッチされない例外を処理するのはそれほど簡単ではありません
キャッチされない例外によって引き起こされる問題
対処方法キャッチされなかった例外
捕捉されない例外のないアプリケーション
アプリケーションをクラッシュさせます
エラーを見て見ぬふりをしていますか?
アプリケーションがクラッシュし、ログが出力され、その後再起動します
Domains モジュールを使用します [翻訳者注: 現在廃止されています]
結論
ノード .js のシングルスレッドの性質により、キャッチされない例外はアプリケーション開発中に注目に値する問題です。 Node.js は、最初にエラー、次にデータというコールバック パターンに従います。次のような例をよく目にします。コールバック関数がエラー オブジェクトを返すと、エラーはすぐにスローされます。
var fs = require('fs'); fs.readFile('somefile.txt', function (err, data) { if (err) throw err; console.log(data); });
ファイル somefile.txt
がない場合にこのプログラムを実行すると、エラーがスローされます。 somefile.txt
这个文件,一个错误将被抛出。
Error: ENOENT, open 'somefile.txt'
这将导致进程崩溃进而影响到整个APP。
这是有意为之,Node.js 不打算把你的应用和服务分隔开。
处理未捕获异常的最佳方式是什么呢?有非常多方法:
你的应用不应该有未捕获错误,这很疯狂。
你应该让你的应用在崩溃后找到未捕获异常,然后修复它们,这也很疯狂。
对错误视而不见,不处理它—这是大多数人做的,然而这糟透了。
你应该让你的应用在崩溃后打印出错误日志,然后借用 upstart
, forever
, monit
之类的东西重启进程。这个方法很实用。
【译者注:现已废弃】你应该开始使用 Domains 模块来处理错误,这是必由之路,虽然这还是 Node.js 的一个试验性功能。
现在我们来详细展开这些方法。
「没有未捕获异常的应用」这个概念对我来说很怪异,任何应用在某个时刻都会有异常而且可能是未捕获的异常。如果你坚持这个观点并把错误扔给用户,那么我觉得你要做好半夜接到电话被告知服务崩溃掉了的准备。
The only defence I can find in this opinion is the fail fast argument. You are going to fix your application quickly if it unavailable. If an application without uncaught exceptions is denial letting your application crash is acceptance. But you are still pushing exception handling onto your users.(原谅我实在想不出怎么翻译这段,如果你有好的想法,请尽快联系我!)
很多人这样做:
<p style="margin-bottom: 7px;">process.on('uncaughtException', function (err) {<br/> console.log(err);<br/>})<br/></p>
这很糟糕,当一个未捕获异常被抛出,你应该意识到你的应用处在一个不正常的状态,这种情况下你无法可靠地运行你的程序。
最初提出 process.on 事件的 Felix Geisendörfer
现在倡议去除它。
通过这个方法你可以让你的应用在发生未捕获异常时立即崩溃,然后利用 forever
或 upstart
这样的工具(几乎可以)立即重启。Node.js 将会把异常写入 STERR
所以你可以把异常重定向到一个日志文件稍晚再通过它拿到错误。这种方法的缺点是,对于错误发生在你的代码之外的 i/o
,不能提供一种优雅的方法来处理临时停电或者网络 i/o
出错的场景。这真是一个利器!— 重启应用并重试。如果你把这种策略与 cluster module
相结合,node 可以自动重启任何抛出错误的 children 并且打印出错误。
var cluster = require('cluster');var workers = process.env.WORKERS || require('os').cpus().length;if (cluster.isMaster) { console.log('start cluster with %s workers', workers); for (var i = 0; i < workers; ++i) { var worker = cluster.fork().process; console.log('worker %s started.', worker.pid); } cluster.on('exit', function(worker) { console.log('worker %s died. restart...', worker.process.pid); cluster.fork(); }); } else { var http = require('http'); http.createServer(function (req, res) { res.end("Look Mum! I'm a server!\n"); }).listen(3000, "127.0.0.1"); } process.on('uncaughtException', function (err) { console.error((new Date).toUTCString() + ' uncaughtException:', err.message) console.error(err.stack) process.exit(1) })
Domains
模块【译者注:现已废弃】Domains
是 Node.js v0.8
版本中新增的一个试验性特性,它使得异常处理变得更加灵活和精确。下面是刚才那个文件不存在的例子,通过使用 domains
var domain = require('domain');var d = domain.create();var fs = require('fs'); d.on('error', function(err) { console.error(err); }); d.run(function() { fs.readFile('somefile.txt', function (err, data) { if (err) throw err; console.log(data); }); });
upstart
、 forever
、 monit
などを借用して、プロセスを再起動する必要があります。 。この方法は非常に実用的です。 🎜🎜🎜🎜【翻訳者注: 現在は廃止されています】エラーを処理するには Domains モジュールを使用し始める必要がありますが、これはまだ Node.js の実験的な機能です。 🎜🎜🎜🎜それでは、これらの方法を詳しく見ていきましょう。 🎜🎜3. キャッチされない例外のないアプリケーション🎜🎜 「キャッチされない例外のないアプリケーション」という概念は、私にとっては奇妙です。どのアプリケーションでも、ある時点で例外が発生し、それがキャッチされない例外になる可能性があります。この点を主張してユーザーにエラーを投げるなら、夜中に電話がかかってきてサービスが落ちたと言われることは覚悟すべきだと思います。 🎜🎜4. アプリケーションをクラッシュさせる🎜🎜 この意見で私が見つけることができる唯一の防御策は、アプリケーションが利用できない場合は、アプリケーションをクラッシュさせることを受け入れることです。 . しかし、あなたは依然として例外処理をユーザーに押し付けています (この段落の翻訳方法が分からないことをお詫びします。良いアイデアがある場合は、できるだけ早く連絡してください!) 🎜🎜5.エラーが見えますか? 🎜🎜多くの人がこれを行います: 🎜rrreee🎜これは良くありません。キャッチされない例外がスローされたときは、アプリケーションが異常な状態にあることを認識する必要があります。その場合、プログラムを確実に実行することはできません。 🎜🎜Felix Geisendörfer
は、最初に process.on イベントを提案しましたが、現在はその削除を主張しています。 🎜🎜6. アプリケーションがクラッシュし、ログが出力され、その後再起動します🎜🎜この方法を使用すると、キャッチされない例外が発生したときにアプリケーションをすぐにクラッシュさせ、その後、forever
または upstart< を使用できます。 /code > このようなツールは (ほぼ) 瞬時に再起動できます。 Node.js は例外を <code>STERR
に書き込むため、例外をログ ファイルにリダイレクトして、後でそこからエラーを取得できます。このアプローチの欠点は、コードの外で発生する一時的な停電やネットワーク i/o
エラーを処理する適切な方法が提供されないことです。問題が発生するシナリオです。なんてツールなんだ! — アプリを再起動して、もう一度試してください。この戦略を cluster module
と組み合わせると、ノードはエラーをスローした子を自動的に再起動し、エラーを出力できます。 🎜rrreee🎜7. Domains
モジュールを使用します [翻訳者注: 現在廃止されました]🎜🎜Domains
は Node.js v0.8
バージョンにあります例外処理をより柔軟かつ正確にする新しい実験的機能が追加されました。以下は、ファイルが存在しない場合の例です。domains
を使用すると、特定のドメインに対してエラー イベントをトリガーできます。また、さまざまなシナリオに応じてさまざまな例外処理を使用することもできます。これにより、例外が発生した場所に応じて例外を処理できます。プロセスを終了することがハンマーでナットを割ることに似ているとすれば、これはプログラムを完全に制御できる精密なメスのようなものです。 🎜var domain = require('domain');var d = domain.create();var fs = require('fs'); d.on('error', function(err) { console.error(err); }); d.run(function() { fs.readFile('somefile.txt', function (err, data) { if (err) throw err; console.log(data); }); });
如果你在产品环境运行 Node.js 你起码应该对如何处理异常有一个想法。目前为止我相信当异常被抛出时,大多数人只是重启应用(也许是优雅地重启),Domains
为应用提供了一种更聪明的面对异常的能力,异常处理器可能会选择简单的清理、关闭某些连接,最坏的情况下,退出进程。关键点就在于你有了选择。
我抛下榔头拾起手术刀的时候应该已经到了
以上がNode.js でキャッチされなかった例外を解決する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。