Nodejs / express, выключение изящно

У меня есть сервер nodejs, на котором выполняется express для сервера http-вызовов. Есть ли рекомендуемый подход к закрытию сервера изящно, если что-то плохое случится? Должен ли я как-то оставить сервер работать?

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

Я:

  1. дождитесь завершения всех http-соединений, прежде чем я разрешу серверу die (а затем перезапустите его).
  2. или я должен попытаться остановить сервер от смерти?

это правильно?

process.on('exit', function () {
  console.log('About to exit, waiting for remaining connections to complete');
  app.close();
});

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

есть ли хороший способ обрабатывать ошибки, или я должен позволить серверу умереть и перезапустить?

3 ответов


не пытайтесь делать ничего необычного с необработанными исключениями. Пусть сервер умрет.

как правило, если обработчик маршрута выдает исключение, Express просто поймает его и вернет HTTP 500 клиенту. Поскольку Express поймал исключение, ваш сервер не аварийно завершит работу.

обычно происходит то, что сбивает сервер, когда исключение выбрасывается внутри обратного вызова; например:

app.get('/foo', function(req, res) {
    db.query(..., function(err, r) {
        throw new Error(); // oops, we'll crash
    });
});

потому что обратный вызов естественно выполняется вне Экспресс-стек вызовов маршрутизатора, нет способа связать его с определенным запросом. Однако вы можете остерегаться такой ситуации:

app.get('/foo', function(req, res, next) {
    db.query(..., function(err, r) {
        try {
            throw new Error();
        } catch(ex) {
            next(ex);
        }
    });
});

Экспресс' next функция принимает ошибку в качестве первого аргумента. Если вы позвоните next С аргументом ошибки он прекратит обработку маршрутов и будет искать обработчик ошибок, или просто верните 500.

конечно, оборачивая все на try/catch вероятно, излишне; большинство вещей на самом деле не бросайте исключения. Вы должны сделать это, только если вы знаю что-то может бросить. В противном случае вы можете оказаться в очень трудном для отладки несогласованном состоянии, проглотив исключения.

важно помнить, что после неожиданного исключения, ваше приложение в неопределенном состоянии. Возможно, что запрос на проблему никогда не будет завершен, и ваше приложение никогда не перезапустится. Или может произойти еще много странных вещей. (Это была проблема с базой данных? Файловая система? Поврежденная память?)

такие ситуации невероятно трудно диагностировать, а тем более отлаживать. Безопаснее и, возможно, лучше просто быстро потерпеть неудачу, сбой и быстро перезагрузить сервер. Да, все подключенные клиенты будут отрезаны, но для них достаточно просто повторить попытку.

если вы беспокоитесь о доступности, используйте модуль кластера так что у вас есть несколько (обычно количество CPU Core) серверные процессы запущены, и один сбой не приведет к сбою всего сайта.


NodeJS завершит работу, когда он не ожидает, что что-то произойдет; в то время как http-сервер ждет на узле соединений остается запущенным.

server.close([callback])

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

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

если вы не хотите ждать завершения соединения, вы можете использовать socket.end() или socket.destroy() на остальные соединения.

см.http://nodejs.org/api/net.html


process.on('exit', function () {
    console.log('About to exit, waiting for remaining connections to complete');
    app.close();
});

эта функция должна выполняться, когда узел существует, а не фактически скажите узлу выйти. Вот один из способов, которым вы можете закончить свой процесс, но он не закончится изящно:

process.exit([code])

завершает процесс с указанным кодом. Если опущено, exit использует код успеха 0.

для выхода с кодом "сбой":

process.exit(1); оболочка, которая выполняла узел, должна видеть код выхода as 1.

посмотреть http://nodejs.org/api/process.html


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


Если вы используете express, вы можете использовать этот модуль npm для изящной обработки остановок.

https://www.npmjs.com/package/express-graceful-shutdown