先记住这个答案
server.close 停止接受新连接,并等待服务器关闭;从 Node 19 起,它也会关闭当时空闲的 HTTP 连接。closeIdleConnections 只清理没有发送请求或等待响应的连接,适合特定兼容和回收场景;closeAllConnections 会强制关闭包括活动请求在内的 HTTP(S) 连接,但不销毁已升级为 WebSocket 等其他协议的 socket。配合使用时先调用 close,再做连接清理,以减少先清理后又接入新连接的竞态。强制操作应放在明确截止策略中,不应当作正常排空的等价替代。
- 停止监听与强制断开活动连接是不同操作
- Node 19 起 close 已包含空闲连接回收
- 升级连接需要对应协议的独立生命周期管理
先观察活动请求是否仍能完成
可以让测试服务器收到请求后等待一个受控信号再结束响应,然后调用 close。此时停止监听不意味着当前响应立即被截断;只有请求完成、连接按关闭规则释放后,服务器关闭回调才有机会执行。
如果在同一个场景追加 closeAllConnections,客户端可能看到连接重置或响应提前结束。验证时应同时记录服务端关闭状态与客户端实际收到的数据,不能只检查关闭回调被调用就宣布请求无损。
空闲清理的版本差异影响兼容代码
早期支持 closeIdleConnections 的版本中,它可用于配合 close 回收 keep-alive 空闲连接。从 Node 19 起 close 已做这部分工作,额外调用通常无需作为必选步骤,但兼容旧范围的库可能仍保留它。
仅调用 closeIdleConnections 不会停止监听,新连接仍可以进入;它不是服务停机入口。同理,在 close 之前先清理所有连接,两个调用之间仍可能接入新连接,因此调用顺序需要表达先停止接入的意图。
升级协议与后台资源不能混进同一个完成计数
HTTP 升级后,socket 已交给新的协议处理。closeAllConnections 不负责销毁这类连接,WebSocket 应先按协议通知关闭,再对逾期连接执行明确终止,并清理相关订阅和定时器。
数据库池、消息消费者和自建 Worker 也不受这些 HTTP 方法管理。完整停机需要分别跟踪资源完成,最后判断是否还有活跃句柄;HTTP server 已关闭不代表进程必定可以退出。
容易答错的地方
- 名字带 All 就认为能清掉所有进程资源
- All 的范围是这个 HTTP 服务管理的连接,并不覆盖升级 socket、其他服务器或数据库句柄。应列出资源所有者并逐类收尾,避免停机卡住时无目标地重复调用同一个方法。
- 每次停机立即强制关闭所有请求
- 这会主动中断本来能够在期限内完成的响应。正常路径应先停止新工作并排空,只有超出约定期限或处于必须终止的条件下才强制处理,并把中断结果留给重试与恢复机制。
面试官还会怎么问?
close 的回调能证明客户端完整收到响应吗?
不能,它反映服务器关闭过程的完成状态,不是远端业务确认。数据交给本地网络层后仍可能遇到网络或客户端问题,关键操作应依靠应用层确认、幂等和结果查询来处理不确定性。
SSE 算升级连接吗?
SSE 通常仍是长时间保持的 HTTP 响应,不等同于 WebSocket 升级。它可能让活动请求长期不结束,因此应在停机时通知客户端重连或结束响应,并为异常连接设置截止策略。
多进程服务要在哪个进程调用 close?
每个实际持有服务器和连接的进程都需要参与停机协调。管理进程发出信号并不等于工作进程资源已经释放,应收集各工作进程状态并保留总期限,避免只关闭其中一层。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。