Как предотвратить node.js от сбоя? try-catch не работает - программирование

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

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

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

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

Ответ 2

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

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

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

Ответ 3

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

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

Ответ 4

Попробуйте supervisor

npm install supervisor
supervisor app.js

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

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

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

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

Ответ 5

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

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

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

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

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

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

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

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

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

Ответ 6

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

Ответ 7

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

https://github.com/vacuumlabs/yacol

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

Ответ 8

Прекрасно работает:

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();
});

Ответ 9

sudo npm install pm2 -g
pm2 start app.js

Все это!