1. ホーム
  2. node.js

[解決済み] node.jsのクラッシュを防ぐにはどうしたらいいですか? try-catchが機能しません

2022-04-21 19:20:26

質問

経験上、PHPサーバーではログやサーバーエンドに例外が投げられますが、node.jsでは単にクラッシュするだけです。私のコードをtry-catchで囲んでも、すべてが非同期で行われるため、うまくいきません。私は、誰もが彼らの生産サーバーで何をするのか知りたいです。

解決方法は?

PM2

まず最初に PM2 に対して Node.js . PM2は、Nodeアプリのクラッシュ処理や監視、ロードバランシングに非常に優れています。PM2 は Node アプリがクラッシュしたり、何らかの理由で停止したり、サーバが再起動したときでも、すぐにアプリを開始します。そのため、コードを管理していても、いつかアプリがクラッシュした場合、PM2はすぐにアプリを再開させることができます。詳しくはこちら。 PM2のインストールと実行

他の回答は、Node自身のドキュメントにあるように、本当に非常識なものです。 http://nodejs.org/docs/latest/api/process.html#process_event_uncaughtexception

もし、他の回答を使っている人がいたら、Node Docsを読んでください。

<ブロッククオート

注意点 uncaughtException は例外処理のための非常に粗雑なメカニズムであり、将来的には削除される可能性があります。

さて、アプリ自体のクラッシュを防ぐための解決策に戻ります。

そこで、Nodeのドキュメント自体が提案していることを、いろいろと調べてみた結果、最終的に思いつきました。

を使用しないでください。 uncaughtException を使用します。 domainscluster の代わりに もし uncaughtException 処理されない例外が発生するたびに、アプリケーションを再起動する必要があります。

ドメイン クラスター

実際に行うのは、エラーを引き起こしたリクエストにエラーレスポンスを送信し、他のリクエストは通常の時間で終了させ、そのワーカーでの新しいリクエストのリッスンを停止することです。

このように、ドメイン使用法はクラスタモジュールと密接に関係しています。なぜなら、ワーカーがエラーを起こしたときに、マスタープロセスが新しいワーカーをフォークすることができるからです。以下のコードを見て、私が言いたいことを理解してください。

を使用することで Domain を使用してプログラムを複数のワーカープロセスに分離することで、弾力性を持たせることができます。 Cluster そのため、より適切に反応し、より安全にエラーを処理することができます。

var cluster = require('cluster');
var PORT = +process.env.PORT || 1337;

if(cluster.isMaster) 
{
   cluster.fork();
   cluster.fork();

   cluster.on('disconnect', function(worker) 
   {
       console.error('disconnect!');
       cluster.fork();
   });
} 
else 
{
    var domain = require('domain');
    var server = require('http').createServer(function(req, res) 
    {
        var d = domain.create();
        d.on('error', function(er) 
        {
            //something unexpected occurred
            console.error('error', er.stack);
            try 
            {
               //make sure we close down within 30 seconds
               var killtimer = setTimeout(function() 
               {
                   process.exit(1);
               }, 30000);
               // But don't keep the process open just for that!
               killtimer.unref();
               //stop taking new requests.
               server.close();
               //Let the master know we're dead.  This will trigger a
               //'disconnect' in the cluster master, and then it will fork
               //a new worker.
               cluster.worker.disconnect();

               //send an error to the request that triggered the problem
               res.statusCode = 500;
               res.setHeader('content-type', 'text/plain');
               res.end('Oops, there was a problem!\n');
           } 
           catch (er2) 
           {
              //oh well, not much we can do at this point.
              console.error('Error sending 500!', er2.stack);
           }
       });
    //Because req and res were created before this domain existed,
    //we need to explicitly add them.
    d.add(req);
    d.add(res);
    //Now run the handler function in the domain.
    d.run(function() 
    {
        //You'd put your fancy application logic here.
        handleRequest(req, res);
    });
  });
  server.listen(PORT);
} 

しかし Domain は非推奨で、Node のドキュメントにあるように、新しい置き換えが来ると削除される予定です。

<ブロッククオート

このモジュールは非推奨です。代替APIが確定した時点で、このモジュールは完全に非推奨となります。ドメインが提供する機能を絶対に必要とするユーザーは、当面の間、このモジュールに依存することができますが、将来的には別のソリューションに移行する必要があることを予期しておく必要があります。

しかし、新しい代替品が導入されない限り、Domain with ClusterはNode Documentationが提案する唯一の良い解決策です。

より深く理解するために DomainCluster 読む

https://nodejs.org/api/domain.html#domain_domain ( Stability: 0 - Deprecated )

https://nodejs.org/api/cluster.html

クラスタとドメインに関するこの素晴らしい詳細な説明を共有してくれた@Stanley Luoに感謝します。

クラスターとドメイン