Как предотвратить узел.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
чтобы убедиться, что ваше приложение работает даже ваш сервер упал, выполните следующие действия:
используйте кластер узлов для разделения нескольких процессов на ядро. Поэтому, если один процесс умер, другой процесс будет автоматически загружаться. Проверьте:http://nodejs.org/api/cluster.html
используйте домен, чтобы поймать асинхронную операцию вместо использования try-catch или uncaught. Я не говорю эта попытка-поймать или не поймать-плохая мысль!
используйте forever / supervisor для мониторинга ваших услуг
добавить демон для запуска приложения узла: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();
});