NodeJS異常処理uncaght Exception編

2945 ワード

王龑—APRIL 08、2015
多くのNodeJSの開発者が異常処理が面倒くさいと文句を言っています.NodeJSでよく見られる異常処理の手段をいくつかのブログで整理します.ほとんどのプログラミング言語と同じように、NodeJSではthrowを通して一つの異常を投げられます.
throw new Error('Catch me');
この異常を捕捉するためにコードをTry Catchに包む必要がある:
try{
    throw new Error('Catch me');
}catch(e){
    // error captured
}
しかし、NodeJSの非同期特性のため、上記のコードはわずかな改造で無効になります.
try{
    process.nextTick(function my_app(){
        throw new Error('Catch me');
    })
}catch(e){
    // never called
}
現実の世界では、異常は常にモジュールの中に発生します.モジュールとは機能を完成させることができるユニットで、簡単な関数でもモジュールとして見なされます.プロジェクトコードの行数が増えるにつれて、非同期ネストの複雑さが増し、常に異常が発生して捕獲されていない場合があります.強力で壮健なNodeJSアプリケーションがないと、捕獲されていない異常が発生してしまい、サービスが利用できなくなります.NodeJSは脆弱だという認識を変えるには、開発者がこの言語の異常処理メカニズムに対する理解を深める必要があります.
uncaught ExceptionuncaughtExceptionは実はNodeJSプロセスのイベントです.プロセスに異常が生じた場合、Try Catchによって捕獲されなかった場合、このイベントがトリガされる.問題を簡略化するために、まず同期の状況の例を見ます.
function external() {
    throw new Error('Catch me');
}

function internal() {
    external();
}

internal(); //error will be thrown
コマンド行でこのプログラムを実行すると、異常な行がスクリプトによって中断されます.次に、Try Catchがないので、異常が発生するまで、NodeJSは異常なデフォルト処理が非常に簡単である.処理コードは以下のようになる.
function _MyFatalException(err){
    if(!process.emit('uncaughtException',err)){
        console.error(err.stack);
        process.emit('exit',1);
    }
}
ノードJSの非捕獲異常に対するデフォルト処理は、-トリガuncaughtExceptionイベント-uncaght Exceptionが傍受されていない場合、-印刷異常のスタック情報-トリガプロセスのexitイベント
NodeJSを使ってサーバーを開発しているなら、偶然の異常をサーバー全体に残したくないです.uncaughtExceptionを傍受すれば、サーバーのプロセスの終了を阻止できるのではないですか?答えはいいですが、そうしないでください.この例を見てください
var express = require('express');

function external(cb) {
    process.nextTick(function () {
        throw new Error();
        cb.call(null, 'sunny');
    })
}

var app = express();
app.get('/weather', function (req, res) {
    external(function (data) {
        res.end('Weather of Beijing is ' + data);
    })
})
app.listen(8018);


function noop(){}
process.on('uncaughtException', noop)
上記の例では、ユーザがサイトにアクセスすると、現地の天気が見られると仮定して、私たちはapache2-utilsを使って要求をシミュレーションします.
ab-n 1000-c 20 http://localhost:8018/weather
しまった!要求はずっと待っています.メモリが上昇します.理由はres.endが永遠に実行されないことであり、既存のI/Oが待機している状態で、開発されたリソースは解放されることがないだけでなく、サーバは新しいユーザ要求を疲れ知らずに受け入れているからである.
NodeJSでの異常処理は高価であり、誤ってメモリ漏れやアプリケーションを不安定にしてしまうことがあります.健康を向上させるために、Clusterモードを利用して、異常が発生した要求に対してエラーコードを返します.エラーが発生したWorkerは新しい要求を受け付けません.Workerを終了します.
本論文の著者はOneAPMエンジニアの王龑です.もっと良い技術記事を読みたいです.OneAPM公式技術ブログにアクセスしてください.