You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker中Sails服务器优雅退出:实现SIGTERM/SIGINT下的Promise逻辑

我来帮你搞定这个Sails服务器优雅退出的问题!核心痛点在于Node.js收到SIGTERM/SIGINT信号后,默认会立刻终止进程,根本等不及你endMe里的异步Promise逻辑执行完成。咱们得调整信号处理的方式,确保异步操作跑完再让进程退出。

解决方案核心思路

要让endMe里的Promise逻辑正常执行,关键是阻止进程立即退出,等所有异步操作(比如数据库写入、Sails服务关闭)完成后,再手动调用process.exit()。

修改后的代码示例

假设你的endMe是包含数据库写入逻辑的异步函数,我们可以这样调整:

const util = require("util");
const setTimeoutPromise = util.promisify(setTimeout);

// 将endMe改为async函数,确保异步逻辑能被等待
async function endMe(reason) {
  console.log(reason);
  try {
    // 1. 执行数据库写入:标记当前实例为"下线"
    await YourInstanceModel.updateOne(
      { instanceId: process.env.INSTANCE_ID } // 假设用环境变量标识实例
    ).set({ status: "offline", offlineAt: new Date() });

    // 2. 优雅关闭Sails服务(如果需要)
    await sails.lower();

    console.log("优雅退出完成:数据库已更新,Sails服务已关闭");
  } catch (err) {
    console.error("退出过程中出错:", err);
    // 出错后必须手动退出,避免进程挂起
    process.exit(1);
  }
}

// 修改信号处理函数为异步,等待endMe执行完成再退出
process.on("SIGTERM", async () => {
  await endMe("exiting - sigterm");
  process.exit(0);
});

process.on("SIGINT", async () => {
  await endMe("exiting - sigint");
  process.exit(0);
});

如果你的endMe原本就返回Promise(不是async函数),也可以用链式调用的方式:

process.on("SIGTERM", () => {
  endMe("exiting - sigterm")
    .then(() => process.exit(0))
    .catch(err => {
      console.error(err);
      process.exit(1);
    });
});
关键注意事项
  • 错误处理不能少:如果数据库写入或Sails关闭失败,一定要捕获错误并手动退出进程,否则进程会一直挂着,最后被Docker强制发送SIGKILL终止,丢失退出逻辑。
  • Docker超时配置:Docker默认在发送SIGTERM后等待10秒,超时会触发SIGKILL。如果你的数据库操作可能超过10秒,需要修改Docker的stop-timeout参数,比如:
    docker run --stop-timeout 30 your-sails-image
    
  • 测试要正确:不要用docker kill测试(会直接发SIGKILL跳过优雅退出),要用docker stop或者在容器内按Ctrl+C(触发SIGINT)来验证逻辑。
  • 确保数据库连接可用:要把数据库写入逻辑放在Sails服务关闭之前,避免连接提前断开导致写入失败。

内容的提问来源于stack exchange,提问作者paul23

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:35:00