Как предотвратить сбой node.js? пробная ловля не работает

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

10 ответов

Решение

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

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

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

PM2

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

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

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

Не использовать uncaughtException использовать domains с cluster вместо. Если вы используете 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 а также Cluster читать

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

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

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

Кластер и Домены

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

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. Я не говорю, что попытка поймать или не пойман - плохая мысль!

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

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

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

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

По умолчанию Node.js обрабатывает такие исключения, выводя трассировку стека в stderr и завершая работу с кодом 1, перекрывая любой ранее установленный process.exitCode.

узнать больше

      process.on('uncaughtException', (err, origin) => {
    console.log(err);
});

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

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

https://github.com/vacuumlabs/yacol

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

Чтобы избежать сбоя сервера nodejs из-за unhandledRejection или uncaughtException, поместите приведенный ниже фрагмент в ваш входной файл main.ts.

      process.on('unhandledRejection', (reason: string, p: Promise<any>) => {
  // I just caught an unhandled promise rejection,
  // since we already have fallback handler for unhandled errors (see below),
  // let throw and let him handle that
  throw reason;
});

process.on('uncaughtException', (error: Error) => {
  // I just received an error that was never handled, time to handle it and then decide whether a restart is needed
  errorManagement.handler.handleError(error);
  if (!errorManagement.handler.isTrustedError(error))
    process.exit(1);
});
Другие вопросы по тегам