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

이 모듈은 더 이상 사용되지 않습니다. 교체 API가 완료되면이 모듈은 더 이상 사용되지 않습니다. 도메인이 제공하는 기능을 반드시 갖추어야하는 사용자는 당분간 도메인에 의존 할 수 있지만 향후 다른 솔루션으로 마이그레이션해야합니다.

그러나 새로운 대체품이 소개되지 않을 때까지 Domain with Cluster가 Node Documentation에서 제안하는 유일한 솔루션입니다.

깊이 이해 Domain하고 Cluster읽으려면

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

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

클러스터 및 도메인에 대한이 훌륭한 설명을 공유해 주신 @Stanley Luo에게 감사드립니다.

클러스터 및 도메인


답변

이 코드를 require 문과 전역 선언 바로 아래에 넣습니다.

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

나를 위해 작동합니다. 내가 마음에 들지 않는 유일한 것은 내가 물건을 추락 시키면 내가 할만 큼 많은 정보를 얻지 못한다는 것입니다.


답변

언급 한 바와 같이 여기에서 찾을 수 있습니다 error.stack같은 오류가 발생한 줄 번호로보다 완벽한 오류 메시지를 제공합니다 :

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


답변

시험 supervisor

npm install supervisor
supervisor app.js

또는 forever대신 설치할 수 있습니다 .

이 작업은 서버를 다시 시작하여 충돌 할 때 서버를 복구하는 것입니다.

forever 코드 내에서 충돌이 발생한 모든 프로세스를 정상적으로 복구 할 수 있습니다.

forever워드 프로세서 프로그램 처리 종료 / 오류에 고체 정보가 있습니다.


답변

try-catch를 사용하면 잡히지 않는 오류를 해결할 수 있지만 일부 복잡한 상황에서는 비동기 함수를 잡는 등의 작업을 제대로 수행하지 못합니다. Node에서 모든 비동기 함수 호출에는 잠재적 인 앱 충돌 작업이 포함될 수 있습니다.

사용 uncaughtException은 해결 방법이지만 비효율적 인 것으로 인식되어 향후 버전의 Node에서 제거 될 가능성이 있으므로 사용하지 마십시오.

이상적인 해결책은 도메인을 사용하는 것입니다 : http://nodejs.org/api/domain.html

서버가 다운 된 경우에도 앱이 작동하고 실행되도록하려면 다음 단계를 사용하십시오.

  1. 노드 클러스터를 사용하여 코어 당 여러 프로세스를 분기하십시오. 따라서 한 프로세스가 종료되면 다른 프로세스가 자동 부팅됩니다. 체크 아웃 : http://nodejs.org/api/cluster.html

  2. try-catch 또는 uncaught를 사용하는 대신 domain을 사용하여 비동기 작업을 포착하십시오. 나는 try-catch 또는 uncaught가 나쁜 생각이라고 말하는 것이 아닙니다!

  3. 영원히 / 관리자를 사용하여 서비스 모니터링

  4. 데몬을 추가하여 노드 앱을 실행하십시오 : http://upstart.ubuntu.com

도움이 되었기를 바랍니다!


답변

pm2 노드 모듈을 사용해보십시오. 일관성이 뛰어나고 훌륭한 문서가 있습니다. 로드 밸런서가 내장 된 Node.js 앱의 프로덕션 프로세스 관리자 이 문제에 대한 uncaughtException을 피하십시오.
https://github.com/Unitech/pm2


답변

UncaughtException은 “매우 조잡한 메커니즘”(그렇기 때문에) 도메인은 더 이상 사용되지 않습니다. 그러나 (논리적) 도메인 주변에서 오류를 잡는 메커니즘이 여전히 필요합니다. 도서관:

https://github.com/vacuumlabs/yacol

당신이 이것을 도울 수 있습니다. 약간의 추가 작성으로 코드 주변에 멋진 도메인 의미를 가질 수 있습니다!