Node.js 服务优雅退出:正确处理 SIGTERM

0 次浏览0 条回复

Docker 停止容器时,先给主进程发 SIGTERM,默认等 10 秒,进程还没退出就发 SIGKILL 强制结束。服务如果不处理 SIGTERM,正在处理的请求会被直接切断,数据库事务也可能停在一半。

JavaScript
const server = app.listen(3000);

function shutdown(signal) {
  console.log(`${signal} received, closing`);
  // 停止接收新连接,等进行中的请求处理完
  server.close(async () => {
    await db.end(); // 关闭数据库连接池
    await redis.quit();
    process.exit(0);
  });
  // 兜底:超过 8 秒强制退出,赶在 SIGKILL 之前
  setTimeout(() => process.exit(1), 8000).unref();
}

process.on("SIGTERM", () => shutdown("SIGTERM"));
process.on("SIGINT", () => shutdown("SIGINT"));

常见的坑

  • 容器入口写成 npm start 时,信号先到 npm,不一定能转发给 node 进程。Dockerfile 里直接写 CMD ["node", "dist/main.js"]。
  • 进程作为容器里的 1 号进程时,没有默认的信号处理,不监听 SIGTERM 就会被忽略,只能等 10 秒后被强杀。要么自己监听,要么用 docker run --init。
  • server.close() 只是不再接收新连接,保持连接(keep-alive)的空闲连接会拖住关闭。Node 18.2 起可以再调用 server.closeIdleConnections()。
  • NestJS 要先调用 app.enableShutdownHooks(),onModuleDestroy、beforeApplicationShutdown 这些钩子才会在收到信号时执行。

0 条回复

返回板块

还没有回复

欢迎发表你的看法。

发表回复