【问题标题】:How to Prevent a Node.js 12 worker Thread from terminating immediately?如何防止 Node.js 12 工作线程立即终止?
【发布时间】:2019-10-13 16:52:04
【问题描述】:

我有一个运行 Express 服务器的 Node.js 应用程序和一个定期执行某些操作的 worker thread

当服务器停止时,我需要清理与工作线程启动时打开的外部系统的连接。

我尝试在进程上为 SIGTERM 和 SIGINT 信号添加处理程序,但这不起作用,工作线程中的处理程序函数没有被调用,当父进程收到 SIGINT 或SIGTERM,虽然父进程也有一个处理程序确实被调用。

这是一个重现问题的简单代码示例:

start.js

const http = require("http");
const express = require("express");
const path = require("path");
const { Worker } = require("worker_threads");

let myWorker = null;

process.on("SIGTERM", stop);
process.on("SIGINT", stop);

const app = express();
const server = http.Server(app);

myWorker = new Worker(path.join(__dirname, "./worker.js"));

myWorker.on("exit", code => console.info(`Worker exited with code ${code}`));

server.listen(3000);

function stop() {
  console.log("Main process: stop()");
  process.exit(0);
}

worker.js

process.on("SIGTERM", stop);
process.on("SIGINT", stop);

setInterval(() => console.log("beep"), 1000);

function stop() {
  console.log("Worker process: stop()");
  process.exit(0);
}

当我启动 soWorker.js 时,当我用 CTRL+C 中断进程时,我会在控制台上得到这个输出:

╰─➤  node start.js
beep
beep
beep
^CMain process: stop()
Worker exited with code 1

预期会发生这样的事情:

╰─➤  node start.js
beep
beep
beep
^CMain process: stop()
Worker process: stop()
Worker exited with code 0

我希望工作线程中的stop函数被调用,这样我就可以使用它来关闭与外部系统的连接,然后优雅地退出工作线程进程并返回代码0。

相反,工作线程以代码 1 退出,which is the default when a worker thread is stopped

我的问题:

当主进程终止时,如何在工作线程中执行一些清理代码?

我是否在上述方法的正确轨道上?

【问题讨论】:

    标签: javascript node.js multithreading worker-thread


    【解决方案1】:

    我主要是在这里吐痰,但我认为这会让你走上正轨:

    添加到 start.js

    process.on('SIGTERM', cleanup);
    process.on('SIGINT', cleanup);
    myWorker.once('exit', stop);
    
    function cleanup() {
      myWorker.postMessage('cleanup');
    }

    worker.js

    const { parentPort } = require('worker_threads');
    
    parentPort.on('message', (value) => {
      if (value === 'cleanup') {
        cleanup();
        //then process.exit(0);
      }
    });

    【讨论】:

    • 当然这不能处理“哦,废话,一切都坏了,OMG”的东西,但这应该允许你拦截 SIGTERM 和 SIGINT,调用你的工作人员正常关闭,一旦完成,正常关闭主应用程序。
    • 嗨 Eddie,谢谢你的回答,我会在赏金用完之前审查它,我真的很忙。所以请耐心等待?
    • ?? 我试过了,效果很好——谢谢你的帮助!
    【解决方案2】:

    以下解决方案应该可以工作-

    • 在工作线程中订阅主线程message事件
    • 在主线程中订阅SIGTERM(或其他)
    • 当你在主线程中捕捉到信号时,向工作线程发送一条消息,请求它清理并退出。 ** 暂时不要退出主线程**。
    • 在主线程中通过订阅exit 事件等待工作线程停止。
    • 当工作线程停止时,退出主线程。

    【讨论】:

    • 嗨 Vikash,谢谢你的回答,我会在赏金用完之前审查它,我真的很忙。所以请耐心等待?
    • 我决定接受 Eddie 的回答,因为它包含代码示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-21
    • 2014-08-02
    • 1970-01-01
    • 2017-02-09
    • 2019-05-03
    • 1970-01-01
    • 2011-05-24
    相关资源
    最近更新 更多