Как предотвратить сбой node.js? попробуй поймать не работает - PullRequest
139 голосов
/ 14 мая 2011

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

Ответы [ 8 ]

120 голосов
/ 15 марта 2014

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

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

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

PM2

Прежде всего, я бы настоятельно рекомендовал установить PM2для Node.js.PM2 отлично справляется с обработкой сбоев и мониторингом приложений Node, а также с балансировкой нагрузки.PM2 немедленно запускает приложение Node в случае его сбоя, остановки по любой причине или даже при перезапуске сервера.Так что, если когда-нибудь, даже после управления нашим кодом, произойдет сбой приложения, PM2 может перезапустить его немедленно.Для получения дополнительной информации Установка и запуск PM2

Теперь вернемся к нашему решению по предотвращению сбоя самого приложения.

Так что после прохождения я наконец-то придумал, чтоСам документ узла предлагает:

Не используйте uncaughtException, используйте domains с cluster.Если вы используете uncaughtException, перезапускайте приложение после каждого необработанного исключения!

DOMAIN с Cluster

Что мы на самом деле делаемотправляет ответ об ошибке на запрос, который вызвал ошибку, позволяя остальным завершить свое обычное время и прекратить прослушивать новые запросы этого работника.

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

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

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

Для более глубокого понимания Domain и Cluster прочитайте

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

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

Спасибо @Stanley Luo за то, что поделились с нами этим замечательным подробным объяснением Cluster and Domains

Cluster &Домены

73 голосов
/ 14 мая 2011

Я поместил этот код прямо под мои требования и глобальные объявления:

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

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

27 голосов
/ 23 февраля 2012

Как уже упоминалось здесь вы найдете error.stack предоставляет более полное сообщение об ошибке, например номер строки, вызвавшей ошибку:

process.on('uncaughtException', function (error) {
   console.log(error.stack);
});
12 голосов
/ 14 мая 2011

Попробуйте supervisor

npm install supervisor
supervisor app.js

Или вы можете вместо этого установить forever.

Все, что вам нужно сделать, это восстановить вашсервер после сбоя путем его перезапуска.

forever может использоваться в коде для корректного восстановления любых процессов, которые аварийно завершаются.

Документы forever содержат достоверную информацию о выходе / обработке ошибокпрограммным способом.

7 голосов
/ 28 августа 2013

Использование try-catch может решить необработанные ошибки, но в некоторых сложных ситуациях он не будет работать правильно, например, перехват асинхронной функции. Помните, что в Node любые вызовы асинхронных функций могут содержать потенциальную операцию сбоя приложения.

Использование 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

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

4 голосов
/ 08 апреля 2016

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

0 голосов
/ 14 февраля 2017

Отлично работает на 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();
});
0 голосов
/ 26 ноября 2016

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

https://github.com/vacuumlabs/yacol

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

...