По моему опыту, php-сервер будет генерировать исключение для журнала или для сервера, но node.js просто просто сбой. Окружать мой код с помощью try-catch не работает, так как все делается асинхронно. Я хотел бы знать, что делают все остальные на своих производственных серверах.
Как предотвратить node.js от сбоя? try-catch не работает
Ответ 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
Все это!