如何在关闭现有请求之前停止接受新请求?

问题描述 投票:0回答:4

运行没有错误:

const app = express();

const server = app.listen(3900, '0.0.0.0', () => {
  console.log('listening...');
});

process.once('SIGINT', () => {

  console.log('got SIGINT.')

  setTimeout(() => {
    console.log('ending process due to SIGINT + subsequent Timeout.')
    process.exit(0);
  }, 3000);

  server.closeIdleConnections();  // <<<
  server.closeAllConnections();  // <<<<

  server.close(err => {
    if (err) {
      console.error(err);
    }
    console.log('closed server, and now shutting down due to SIGINT.')
    process.exit(0);
  });
});

但我的问题是 - 这是在结束现有连接/请求之前停止接受新连接的最佳方法吗?

“空闲”连接是如何定义的?

node.js http https httpserver
4个回答
1
投票

在您的代码中,您尝试处理 'SIGINT' 信号以正常关闭服务器。但是,方法 'server.closeIdleConnections()''server.closeAllConnections()' 不是标准 Express API 的一部分。相反,您应该使用 'server.close()' 停止接受新连接,然后等待现有连接完成,然后再关闭服务器。这是代码的更新版本:

javascript

const app = express();

const server = app.listen(3900, '0.0.0.0', () => {
  console.log('listening...');
});

process.once('SIGINT', () => {
  console.log('got SIGINT.');

  server.close((err) => {
    if (err) {
      console.error(err);
      process.exit(1);
    }

    console.log('closed server, and now shutting down due to SIGINT.');
    process.exit(0);
  });
});

此代码将通过关闭服务器并等待现有连接完成然后退出进程来正常关闭您的服务器。关于您关于“空闲”连接的问题,在 Express 等 Web 服务器的上下文中,空闲连接是指打开但不主动发送或接收数据的连接。 server.close() 方法将等待这些空闲连接完成,然后再关闭服务器。


0
投票

在golang中,我们可以这样做:

server := &http.Server{
      // ...
}

listener, err := net.Listen("tcp", addr)

然后这样做:

if err := listener.Close(); err != nil { // Stop listening for new connections
      // err
}
if err := server.Close(); err != nil { // Close all current/existing connections
       // err
}

第一个调用停止接受新连接,第二个调用关闭所有现有连接。将它们分开很好,但不知道如何使用 node.js 来做到这一点


0
投票

但我的问题是 - 这是在结束现有连接/请求之前停止接受新连接的最佳方法吗?

您的质量不是“最好”,但让我们假设您想要优雅地关闭 HTTP 服务器,而不会因为新的连接正在旋转而中断正在进行的连接。

closeAllConnections()
会中断任何飞行中的连接,所以不要调用它。

“空闲”连接是如何定义的?

空闲连接是由 HTTP 客户端打开但当前未发送 HTTP 请求或等待 HTTP 响应的 TCP 连接。这些通常可以安全关闭。


0
投票

这是在结束现有连接/请求之前停止接受新连接的最佳方法吗?

我想“最好”是主观的,这取决于应用程序。然而,在允许 asynchronous

server.closeAllConnections()
完成工作之前调用 synchronous
server.close()
并不是停止任何正在进行的连接(当前发送请求或等待响应的连接)的最优雅的方法。简而言之,我想说,由于
closeAllConnections
的突然性,这不是在结束现有连接之前停止接受新连接的最优雅的方式。

“空闲”连接是如何定义的?

我会将您链接到文档,其中指出空闲连接是指连接到此服务器且不发送请求或等待响应的连接。

为了使您的

SIGINT

 处理程序更加优雅,我建议通过删除对 
server.closeAllConnections()
 的调用并将您的 
setTimeout
 嵌套在 
close
 回调内部来进行稍微修改。沿着这些思路:

process.once('SIGINT', () => { /** * Immediately close any idle connections. * May not be strictly necessary since as of Node v19.0.0 * server.close() will also close idle connections before * returning / firing the 'close' event. * * Either way, it may reduce the workload of server.close() * by minimizing the connections it must close or wait to * finish to those that were already active, or only created * in the short time span between calling closeIdleConnections() * and close(). */ server.closeIdleConnections() // Now stop the server from accepting new connections while keeping existing connections. server.close((err) => { // Force close all connections after a specified timeout setTimeout(() => { server.closeAllConnections() process.exit(0) }, 3000).unref() // prevents the event loop from remaining active so your server can shutdown earlier if this timeout is not needed. process.exit(err ? 1 : 0) }) })
请注意,如果您尝试关闭未运行的服务器,则对 

server.close

 的回调只会收到错误。这在 
net.Server.close()
 的文档中已注明。

© www.soinside.com 2019 - 2024. All rights reserved.