Programming

node.js가 충돌하는 것을 어떻게 방지합니까?

procodes 2020. 6. 16. 22:43
반응형

node.js가 충돌하는 것을 어떻게 방지합니까? try-catch가 작동하지 않습니다


내 경험상 PHP 서버는 로그 또는 서버 쪽에서 예외를 throw하지만 node.js는 단순히 충돌합니다. 모든 코드가 비동기 적으로 수행되므로 try-catch로 코드를 둘러 쌀 수 없습니다. 프로덕션 서버에서 다른 사람들이 무엇을하는지 알고 싶습니다.


http://nodejs.org/docs/latest/api/process.html#process_event_uncaughtexception 에서 Node의 자체 문서를 읽을 수 있으므로 다른 답변은 정말 미쳤습니다.

누군가 다른 명시된 답변을 사용하는 경우 노드 문서를 읽으십시오.

참고 uncaughtException예외 처리를위한 매우 조질기구이며 향후 제거 될 수있다

PM2

우선, 나는 높게 설치하는 것이 좋습니다 PM2위해 Node.js. PM2는 충돌을 처리하고 노드 앱을 모니터링하고로드 밸런싱에 정말 좋습니다. PM2는 충돌이 발생하거나 어떤 이유로 든 서버가 다시 시작될 때마다 Node 앱을 즉시 시작합니다. 따라서 언젠가 코드를 관리 한 후에도 앱이 중단되면 PM2가 즉시 다시 시작할 수 있습니다. 자세한 내용은 PM2 설치 및 실행

이제 앱 자체의 충돌을 막기위한 솔루션으로 돌아 왔습니다.

그래서 나는 마침내 Node 문서 자체가 제안하는 것을 생각해 냈습니다.

사용하지 마십시오 uncaughtException, 사용 domains으로 cluster대신. 를 사용하는 경우 uncaughtException처리되지 않은 모든 예외 후에 응용 프로그램을 다시 시작하십시오!

DOMAIN클러스터

우리가 실제로하는 일은 오류를 유발 한 요청에 대해 오류 응답을 보내면서 다른 사람들이 정상적인 시간에 끝내도록하고 해당 작업자의 새 요청을 듣지 않는 것입니다.

이런 식으로, 마스터 프로세스가 작업자에게 오류가 발생하면 마스터 프로세스가 새 작업자를 분기 할 수 있으므로 도메인 사용은 클러스터 모듈과 함께 사용됩니다. 내가 의미하는 바를 이해하려면 아래 코드를 참조하십시오

을 사용하고을 사용하여 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중단 보류하고 새로운 교체로 노드의 문서에 명시되어 제공으로 제거됩니다

This module is pending deprecation. Once a replacement API has been finalized, this module will be fully deprecated. Users who absolutely must have the functionality that domains provide may rely on it for the time being but should expect to have to migrate to a different solution in the future.

But until the new replacement is not introduced, Domain with Cluster is the only good solution what Node Documentation suggests.

For in-depth understanding Domain and Cluster read

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

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

Thanks to @Stanley Luo for sharing us this wonderful in-depth explanation on Cluster and Domains

Cluster & Domains


I put this code right under my require statements and global declarations:

process.on('uncaughtException', function (err) {
  console.error(err);
  console.log("Node NOT Exiting...");
});

works for me. the only thing i don't like about it is I don't get as much info as I would if I just let the thing crash.


As mentioned here you'll find error.stack provides a more complete error message such as the line number that caused the error:

process.on('uncaughtException', function (error) {
   console.log(error.stack);
});

Try supervisor

npm install supervisor
supervisor app.js

Or you can install forever instead.

All this will do is recover your server when it crashes by restarting it.

forever can be used within the code to gracefully recover any processes that crash.

The forever docs have solid information on exit/error handling programmatically.


Using try-catch may solve the uncaught errors, but in some complex situations, it won't do the job right such as catching async function. Remember that in Node, any async function calls can contain a potential app crashing operation.

Using uncaughtException is a workaround but it is recognized as inefficient and is likely to be removed in the future versions of Node, so don't count on it.

Ideal solution is to use domain: http://nodejs.org/api/domain.html

To make sure your app is up and running even your server crashed, use the following steps:

  1. use node cluster to fork multiple process per core. So if one process died, another process will be auto boot up. Check out: http://nodejs.org/api/cluster.html

  2. use domain to catch async operation instead of using try-catch or uncaught. I'm not saying that try-catch or uncaught is bad thought!

  3. use forever/supervisor to monitor your services

  4. add daemon to run your node app: http://upstart.ubuntu.com

hope this helps!


Give a try to pm2 node module it is far consistent and has great documentation. Production process manager for Node.js apps with a built-in load balancer. please avoid uncaughtException for this problem. https://github.com/Unitech/pm2


UncaughtException is "a very crude mechanism" (so true) and domains are deprecated now. However, we still need some mechanism to catch errors around (logical) domains. The library:

https://github.com/vacuumlabs/yacol

can help you do this. With a little of extra writing you can have nice domain semantics all around your code!


Works great on restify:

server.on('uncaughtException', function (req, res, route, err) {
  log.info('******* Begin Error *******\n%s\n*******\n%s\n******* End Error *******', route, err.stack);
  if (!res.headersSent) {
    return res.send(500, {ok: false});
  }
  res.write('\n');
  res.end();
});

참고URL : https://stackoverflow.com/questions/5999373/how-do-i-prevent-node-js-from-crashing-try-catch-doesnt-work

반응형