【问题标题】:Detach node child process after receiving a first message收到第一条消息后分离节点子进程
【发布时间】:2015-05-12 21:24:39
【问题描述】:

我正在使用 node.js 构建一个系统,用户可以在其中从 Web 界面生成工作进程,但我无法为系统结合这两个标准:

  1. Web 服务器进程和工作进程应该独立运行,这样如果 Web 服务器崩溃,工作进程不会受到影响。
  2. 母进程应该能够从工作进程接收至少一条初始消息。在该消息之后,我想将工作进程的输出记录到文件中。

我已经能够自己完成这两个标准,但不能一起完成。以下是我的代码的相关部分目前的样子:

function spawnWorker (id, callback) {
    var worker = spawn("node", [require.resolve("worker"), id], {
        detached: true,
        stdio: ["ignore", "pipe", "pipe"]
    });

    worker.unref();

    var logfile = fs.createWriteStream("foo.log");

    worker.stdout.once("data", function (data) {
        worker.stdout.pipe(logfile);
        worker.stderr.pipe(logfile);

        callback(undefined, data.toString());
    });
}

这符合标准 2(即,它接收来自工作人员的第一条消息并将所有后续输出重定向到文件),但如果我杀死母进程,工作进程也会被杀死,即使输出已经重定向。

我的猜测是,这是因为工人的 stdout 和 stderr 在发送到文件流之前通过管道传输到母进程。如果我在生成进程时传入流,根据docs,节点将改为在工作进程中复制该流:

流的底层文件描述符在子进程中重复[...]

有没有办法在收到第一条消息后删除母进程和工作进程之间的连接?或者我应该使用某种类型的 RPC 来完成此任务,如果是这样,一旦通信,对于这条消息,什么是一个好的选择?

【问题讨论】:

    标签: javascript node.js


    【解决方案1】:

    我使用节点的net 模块解决了这个问题,该模块在启动时传递给工作人员的随机端口上生成服务器(因此它知道在准备好时将响应发送到哪里)。

    这是我的解决方案的实现示例,澄清一下,这符合以下要求:

    1. 保存工作进程的日志输出,
    2. 保持工作进程与母进程分离(这样如果后者崩溃,也不会影响工作进程)

    server.js

    var net = require("net"),
        fs = require("fs"),
        spawn = require("child_process").spawn,
        randomPort = require("get-port");
    
    randomPort(function (port) {
        var server = net.createServer(function (connection) {
            connection.on("data", function (data) {
                server.close();
                /**
                 * Response received from worker, this is where you would put
                 * your logic that returns a response to the client that initiated
                 * the request to the server.
                 */
            });
        });
    
        server.listen(port);
    
        var logfile = fs.createWriteStream("log");
        var worker = spawn("node", ["worker.js", port], {
            detached: true,
            stdio: ["ignore", logfile, logfile]
        });
    
        worker.unref();
    
        worker.on("close", function (status, message) {
            console.log("worker closed", status, message);
        });
    });
    

    worker.js

    var net = require("net");
    
    var options = process.argv.slice(2),
        rpcPort = Number(options[1]);
    
    var client = net.connect({port: rpcPort}, function () {
        client.end(JSON.stringify({started: true}}));
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-10
      • 2020-05-12
      • 1970-01-01
      • 1970-01-01
      • 2016-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多