Как предотвратить узел.JS из сбой? try-catch не работает

по моему опыту, php-сервер выдаст исключение из журнала или на серверную часть, но узел.js просто падает. Окружение моего кода с помощью try-catch также не работает, так как все выполняется асинхронно. Я хотел бы знать, что делают все остальные на своих производственных серверах.

8 ответов


другие ответы действительно безумны, поскольку вы можете читать собственные документы узла на http://nodejs.org/docs/latest/api/process.html#process_event_uncaughtexception

если кто-то использует другие заявленные ответы, прочитайте документы узла:

отметим, что uncaughtException очень грубый механизм для обработки исключений и может быть удален в будущем

Итак, после прохождения я, наконец, придумал, какой узел сам документ предлагает:

не используйте его, используйте domains С . Если вы используете 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 в ожидании осуждения и будет удален, как новая замена приходит, как указано в документации узла

этот модуль ожидает устаревания. После завершения замены API этот модуль будет полностью устаревшим. Пользователи, которые абсолютно должны иметь функциональность, предоставляемую доменами, могут полагаться на нее в настоящее время, но должны ожидать, что в будущем им придется перейти на другое решение.

но пока новая замена не введена, домен с кластером-единственное хорошее решение, которое предлагает документация узла.

для глубокого понимания 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 может решить необработанные ошибки, но в некоторых сложных ситуациях он не будет делать работу правильно, например, ловить асинхронную функцию. Помните, что в узле любые асинхронные вызовы функций могут содержать потенциальную операцию сбоя приложения.

С помощью uncaughtException является обходным путем, но он признан неэффективным и, вероятно, будет удален в будущих версиях Node, поэтому не рассчитывайте на него.

идеальным решением является использование домена: http://nodejs.org/api/domain.html

чтобы убедиться, что ваше приложение работает даже ваш сервер упал, выполните следующие действия:

  1. используйте кластер узлов для разделения нескольких процессов на ядро. Поэтому, если один процесс умер, другой процесс будет автоматически загружаться. Проверьте:http://nodejs.org/api/cluster.html

  2. используйте домен, чтобы поймать асинхронную операцию вместо использования try-catch или uncaught. Я не говорю эта попытка-поймать или не поймать-плохая мысль!

  3. используйте forever / supervisor для мониторинга ваших услуг

  4. добавить демон для запуска приложения узла:http://upstart.ubuntu.com

надеюсь, что это помогает!


попробуйте модуль узла pm2, он очень последователен и имеет отличную документацию. Менеджер производственного процесса для узла.приложения js со встроенным балансировщиком нагрузки. пожалуйста, избегайте uncaughtException для этой проблемы. https://github.com/Unitech/pm2


UncaughtException - "очень грубый механизм" (так верно), и Домены теперь устарели. Однако нам все еще нужен какой-то механизм для улавливания ошибок вокруг (логических) доменов. Библиотека:

https://github.com/vacuumlabs/yacol

может помочь вам сделать это. С небольшим количеством дополнительной записи вы можете иметь хорошую семантику домена вокруг вашего кода!


отлично работает на 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();
});