NodeJSでdomainモジュールを使って非同期を捕獲する
4703 ワード
背景
最近、オンラインで重要なサービスが発生しました.授業中の教師の大面積の断線が発生しました.私たちはエラーログを通じて
まず、私達はprocess上のuncaught Exception事件を思い付きました.プロcessのuncaught Exceptionイベントにコールバックを登録したら、サービスは異常に終了しません.見たところとても美しいです.少なくとも私達のサービスはキャンセルしません.しかし、他の問題を持ってきました.
uncaught Exceptionイベント
uncaught Exceptionは、NodeJSプロセスの一つのイベントです.プロセス中に異常が発生し、異常が何のtry...catchによっても捕獲されないと、このイベントがトリガされます.
同期異常を例にとって、NodeJSの異常に対するデフォルト処理を紹介します.
uncaught Exceptionイベント発生の条件プログラムに異常が発生しました. 、異常はtry...catchに捕獲されていない 欠点と問題は異常なコンテキストを取得できませんでした. は友好的な異常な処理を与えることができない.例えば、インターフェースが はメモリリークの原因となります.uncaghtExceptionイベントが発生すると、現在の環境のスタックが失われ、Nodeが正常にメモリを回収できなくなり、メモリが漏洩する恐れがあります.
domainモジュールを使って非同期異常を捕捉する
注意:domainモジュールは破棄されます.
domainモジュールは、異常な処理方式を簡略化し、try...catch.が処理できます.捕獲できない異常です.コンテキストが失われず、プログラムが終了することもありません.
私達の古いプロジェクトはexpressフレームを使っていますので、中間部品の方式を使って、要求中の非同期異常を処理します.コードは以下の通りです
いつdomannのerror事件を触発しますか?プロセスは異常を投げました.何のtry catchに捕獲されませんでした.この時プロシーズ全体のprocessFatalを触発します.この時domann小包の中で、domann上でerror事件を触発します.反対に、process上でuncaughtExceptionイベントをトリガします.
domainモジュールについてもっと知りたいなら、この文章を読んでください.
方案を最適化する
domainは使いやすいですが、万能ではありません.部分異常を捕まえられない場合もあります.サービスのために切らないようにします.私は
基礎版
domain+uncaught Exception
アップグレード版
domain+uncaught Exception+Custer
Clausterモジュールを使って、複数の作業スレッドを開くことができます.domainで捕獲できない異常があった場合、
domainモジュールはまもなく廃棄されますが、それでも使用できます.オンライン異常を発見しました.
参考資料 Node.jsは、domanモジュールを使用して非同期エコー中の異常を捕捉する. NodeJS API-process event uncaghttexception Node安定性の研究の心得 CNode-Node.js非同期異常処理とdomainモジュール解析 NodeJS異常処理uncaght Exception編 2018:Using Node.js domans in production
最近、オンラインで重要なサービスが発生しました.授業中の教師の大面積の断線が発生しました.私たちはエラーログを通じて
socket hang up
のエラーを確認しました.しかし、エラーによって異常なコードが位置決めできませんでした.アクセスログを調べても、あたご前にエラーが発生したインターフェースを特定できません.コードの中で異常を捕獲することができることを期待しています.このようにサービスがキャンセルされないようにして、異常な文脈を取得して、ミスを見つけたいです.events.js:183
throw er; // Unhandled 'error' event
^
Error: socket hang up
at TLSSocket.onHangUp (_tls_wrap.js:1137:19)
at Object.onceWrapper (events.js:313:30)
at emitNone (events.js:111:20)
at TLSSocket.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1064:12)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
at process._tickCallback (internal/process/next_tick.js:180:9)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] start: `node ./app/bin/www;`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /root/.npm/_logs/2018-09-30T08_22_32_703Z-debug.log
uncaught Exceptionを使って非同期を捕獲します.まず、私達はprocess上のuncaught Exception事件を思い付きました.プロcessのuncaught Exceptionイベントにコールバックを登録したら、サービスは異常に終了しません.見たところとても美しいです.少なくとも私達のサービスはキャンセルしません.しかし、他の問題を持ってきました.
uncaught Exceptionイベント
uncaught Exceptionは、NodeJSプロセスの一つのイベントです.プロセス中に異常が発生し、異常が何のtry...catchによっても捕獲されないと、このイベントがトリガされます.
同期異常を例にとって、NodeJSの異常に対するデフォルト処理を紹介します.
process.on('uncaughtException', (error) => {
console.log('call uncaughtException handle');
});
//
nonexistentFunc();
まず、processのuncaghtExceptionイベントを登録して、存在しない関数を実行しました.このプログラムを実行すると、関数nonexistentFunc
が存在しないため、プログラムは異常を投げます.try...catch...処理が行われていないため、異常が発生するまで泡が発生します.NodeJSの異常に対するデフォルト処理は、以下のようなコードである.function _MyFatalException(err){
if(!process.emit('uncaughtException',err)){
console.error(err.stack);
process.emit('exit',1);
}
}
ノードJSの異常に対するデフォルト処理の順序は、まずuncaughtException
イベントをトリガし、イベントが傍受されていない場合、スタックのエラー情報を印刷し、最後にプロセスの終了イベントを起動する.イベントが傍受されると、uncaughtException
の登録コールバックが処理される.uncaught Exceptionイベント発生の条件
uncaughtException
で発生した場合、レスポンスオブジェクト(コンテキストが失われました)が取得できず、起動者サービスに現在異常が発生していることを通知します.uncaughtException
を使用して異常を捕捉すると、メモリが漏れます.提案された使用方法は、uncaughtException
イベントが発生したときに、errorを記録し、Nodeプロセスを終了してサービスを再開することである.(その後、私たちはプロジェクトの中でこのようにしていませんでした..業務は再起動できません.)domainモジュールを使って非同期異常を捕捉する
注意:domainモジュールは破棄されます.
domainモジュールは、異常な処理方式を簡略化し、try...catch.が処理できます.捕獲できない異常です.コンテキストが失われず、プログラムが終了することもありません.
私達の古いプロジェクトはexpressフレームを使っていますので、中間部品の方式を使って、要求中の非同期異常を処理します.コードは以下の通りです
const domain = require('domain');
app.use((req, res, next) => {
const req_domain = domain.create();
req_domain.on('error', (err) => {
console.log(err); //
res.send(500, err.stack);
});
req_domain.run(next);
});
ミドルウェアでは、まずdomain
オブジェクトを作成し、error
イベントのコールバックを登録し、最後に作成ドメインのコンテキストでnext関数を実行します.いつdomannのerror事件を触発しますか?プロセスは異常を投げました.何のtry catchに捕獲されませんでした.この時プロシーズ全体のprocessFatalを触発します.この時domann小包の中で、domann上でerror事件を触発します.反対に、process上でuncaughtExceptionイベントをトリガします.
domainモジュールについてもっと知りたいなら、この文章を読んでください.
方案を最適化する
domainは使いやすいですが、万能ではありません.部分異常を捕まえられない場合もあります.サービスのために切らないようにします.私は
uncaughtException
事件を使ってポケットをすることができます.基礎版
domain+uncaught Exception
domain
は、大部分の異常を捕獲し、かつ適切に異常終了を処理し、uncaughtException
はサービスの切断を回避する.アップグレード版
domain+uncaught Exception+Custer
Clausterモジュールを使って、複数の作業スレッドを開くことができます.domainで捕獲できない異常があった場合、
uncaughtException
で捕獲したとき、メモリ漏れを避けるために、現在のworkプロセスを終了することができます.具体的な実現は以下の通りです.const cluster = require('cluster');
process.on('uncaughtException', (err) => {
console.log(err); //
server.close(); //
// master
if (cluster.worker) {
cluster.worker.disconnect();
}
});
締め括りをつけるdomainモジュールはまもなく廃棄されますが、それでも使用できます.オンライン異常を発見しました.
参考資料