Лучшие практики обработки исключений в Node.js
Я только что начал тестировать node.js несколько дней назад и заметил, что Node завершает работу каждый раз, когда в моей программе возникает необработанное исключение. Это отличается от обычного серверного контейнера, с которым я знаком, где только рабочий поток завершает свою работу при возникновении необработанных исключений, а контейнер все еще может принимать запросы. У меня возникло несколько вопросов:
- Является ли
process.on('uncaughtException')
единственным эффективным способом защиты от этого? - Поймает ли
process.on('uncaughtException')
необработанные исключения во время выполнения асинхронных процессов? - Существует ли модуль, который уже реализован (например, отправка электронной почты или запись в файл), который я мог бы использовать в случае необработанных исключений?
Я был бы признателен за любые указания или статьи, которые бы показали мне общепринятые лучшие практики для обработки необработанных исключений в node.js.
4 ответ(ов)
Вы можете перехватывать необработанные исключения, но это имеет ограниченное применение. Дополнительную информацию можно найти по ссылке: http://debuggable.com/posts/node-js-dealing-with-uncaught-exceptions:4c933d54-1428-443c-928d-4e1ecbdd56cb.
Для перезапуска процесса Node.js в случае его сбоя вы можете использовать такие инструменты, как monit
, forever
или upstart
. Лучшее, на что вы можете надеяться, — это корректное завершение работы приложения (например, сохранить все данные в памяти в обработчике необработанных исключений).
Один из случаев, когда использование конструкции try-catch может быть оправдано, - это в цикле forEach. Хотя этот цикл синхронный, вы не можете просто использовать оператор return в внутренней области видимости. Вместо этого можно применить подход с try и catch, чтобы возвратить объект ошибки в соответствующей области видимости. Рассмотрим следующий пример:
function processArray() {
try {
[1, 2, 3].forEach(function() { throw new Error('exception'); });
} catch (e) {
return e;
}
}
Это комбинация подходов, описанных выше @balupton.
Обработка ошибок была хорошо обсуждена здесь, но стоит помнить, что важно записывать ошибки куда-то, чтобы вы могли их просмотреть и исправить проблемы.
Bunyan — популярный фреймворк для логирования в Node.js. Он поддерживает запись в разные выходные места, что делает его полезным для локальной отладки, если избегать использования console.log.
В обработчике ошибок вашего приложения вы можете записать ошибку в файл журнала.
var log = bunyan.createLogger({
name: 'myapp',
streams: [
{
level: 'error',
path: '/var/tmp/myapp-error.log' // логировать ошибки в этот файл
}
]
});
Это может занять много времени, если у вас много ошибок и/или серверов для проверки, поэтому стоит рассмотреть использование инструмента вроде Raygun (дисклеймер, я работаю в Raygun), чтобы группировать ошибки — или использовать оба подхода вместе.
Если вы решите использовать Raygun, его довольно легко настроить:
var raygunClient = new raygun.Client().init({ apiKey: 'ваш API ключ' });
raygunClient.send(theError);
В связке с инструментами вроде PM2 или forever ваше приложение сможет аварийно завершиться, зафиксировать, что произошло, и перезапуститься без особых проблем.
Использование доменов для обработки исключений на уровне API или функции может быть интересным подходом, особенно если вы хотите упростить код обработки исключений в каждой асинхронной функции. Однако следует учесть несколько моментов.
Во-первых, действительно, при использовании новых доменов для каждой функции overhead может быть минимальным, и в некоторых случаях производительность может быть даже лучше, чем при использовании конструкции try-catch
. Это связано с тем, что домены способны захватывать исключения, возникающие в асинхронных вызовах, без необходимости оборачивать каждую часть кода в try-catch
.
Тем не менее, использование доменов в Node.js считается устаревшим и может быть не самым лучшим выбором. В последних версиях Node.js рекомендуется использовать конструкции async/await
вместе с try-catch
для обработки исключений, так как это более современный и понятный способ управления ошибками. Кроме того, домены могут привести к путанице в управлении контекстом и сложности отладки.
В заключение, если вы все же решите использовать домены для обработки исключений, учитывайте, что это может упростить код, но также может вызвать трудности с отладкой и поддержкой. Рекомендуется протестировать ваш конкретный случай, чтобы узнать, как это повлияет на производительность в вашем приложении.
Чтение переменных окружения в Node.js
Как получить полный объект в console.log() Node.js, а не '[Object]'?
Различия между Socket.IO и WebSockets
Правильный способ использования try/except с модулем requests в Python?
Mockito: Тестирование void метода, который выбрасывает исключение