Express服务优雅关闭时如何停止接收新请求仅处理存量请求并响应
Express 服务优雅关闭实现方案
核心实现思路
- 触发关闭流程时,首先标记服务为正在关闭状态,拒绝所有新进来的请求,返回
503 Service Unavailable状态码,通知上游流量调度组件停止向当前节点转发请求 - 统计当前正在处理的活跃请求数量,所有存量请求处理完成后再关闭服务进程
- 配置最大等待超时时间,避免极端情况下进程无限挂起无法退出
具体代码实现
首先添加全局状态标记和活跃请求计数器,对应的中间件要放在所有路由规则之前,确保所有请求都会经过统计逻辑:
// 全局状态标记 let isShuttingDown = false; let activeRequests = 0; // 请求统计中间件 app.use((req, res, next) => { if (isShuttingDown) { // 已进入关闭流程,直接拒绝新请求 res.status(503).send('Service is shutting down'); return; } activeRequests++; // 响应结束后减少活跃请求计数 res.on('finish', () => { activeRequests--; // 处于关闭流程且无活跃请求时直接退出 if (isShuttingDown && activeRequests === 0) { process.exit(0); } }); next(); });
之后修改关闭逻辑,同时监听系统的进程退出信号触发优雅关闭流程:
function gracefulShutdown() { console.log('Start graceful shutdown process'); // 标记关闭状态,停止受理新请求 isShuttingDown = true; // 停止监听新端口 server.close(() => { log('HTTP server closed'); }); // 配置最大等待时间,这里设为30秒覆盖你最长20秒的接口耗时,超时强制退出 setTimeout(() => { console.log(`Force shutdown after timeout, remaining active requests: ${activeRequests}`); process.exit(1); }, 30 * 1000); } // 监听进程退出信号 process.on('SIGTERM', gracefulShutdown); process.on('SIGINT', gracefulShutdown);
注意事项
- 如果服务前有Nginx、负载均衡等反向代理组件,可以配合调整健康检查规则,触发关闭时先让健康检查返回失败,等上游流量完全切走后再处理存量请求,效果会更平稳
- 如果服务有用到数据库、Redis等外部资源连接,记得在进程退出前主动关闭对应连接,避免资源泄露
内容的提问来源于stack exchange,提问作者ankalal
相关产品推荐
相关产品推荐

