Остановить новый запрос к серверу Express, но может обрабатывать более старые запросы и отправлять ответ

Я работаю над плавным завершением работы. В моем приложении есть API-интерфейсы, которые отвечают за 10-20 секунд.

      server.close(
    () => {
      log('HTTP server closed')
    }
  );

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

2 ответа

Узел .close()метод делает почти точно то, что вы просите его сделать. Конкретно:

server.close([обратный вызов])
Добавлено в: v0.1.90
callbackВызывается, когда сервер закрыт.
Returns: <net.Server> Запрещает
серверу принимать новые соединения и сохраняет существующие соединения.

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

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

  1. Принудительно закрыть соединения без активных запросов connection.destroy()
  2. Отклонять запросы, полученные по существующим соединениям request.res.end()

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

Рекомендуемые обновления:

  • регистрация открытых соединений и их запросов во время выключения, если это занимает больше времени, чем разумно
  • Принудительное закрытие запросов и соединений через некоторое заранее определенное время (может потребоваться зарегистрировать, какие из них были принудительными, чтобы вы знали, застревают ли определенные запросы)
  • Проверьте любые запросы longpoll, они неопределенные и поэтому должны быть принудительно уничтожены ( text/event-streamзаголовки или путь, который вы знаете, обслуживает только этот контент)

Вы можете внедрить промежуточное ПО, которое немедленно отклоняет входящие соединения, как только вы начинаете процесс выключения.

      // set this flag to true when you want to start 
//   immediately rejecting new connections
let pendingShutdown = false;

// first middleware
app.use((req, res, next) => {
   if (pendingShutdown) {
       // immediately reject the connection
       res.sendStatus(503);
   } else {
       next();
   }
});

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

      pendingShutdown = true;
server.close();

В NPM также есть несколько модулей, которые также предоставляют различные алгоритмы отключения.

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

Другие вопросы по тегам