0

我将 NodeJS 与 PhantomJS 一起使用。我的目标是使用节点集群创建 4 个节点实例,每个实例都有 2 个幻像子节点。我的代码如下所示:

集群.js:

var numCPUs = 4;

if (cluster.isMaster) {

    for (var i = 0; i < numCPUs; i++) {
        cluster.fork();
    }

    cluster.on('exit', function(worker, code, signal) {
        console.log('worker ' + worker.process.pid + ' died');
        cluster.fork();
    });

} else {
    require("./app");
}

App.js 看起来像这样:

var instances = [];
var phantom = require('phantom');

function InstanceManager(instCount) {
    for (var i = 0; i < instCount; i++) {
           phantom.create(function(phantomInstance) {
            instances.push({
                cycle: 0,
                locked: false,
                instance: phantomInstance
            });
        });
    }
}

InstanceManager(2);

setInterval(function() {
    var i = 0;
    console.log('--' + instances.length);
}, 5000);

因此,cluster.js在节点控制台中运行预期输出后,每 5 秒应该是:

--2
--2
--2
--2

但看起来像这样:

--0
--0
--0
--8

为什么幻影实例没有附加到正确的工作人员?

4

1 回答 1

3

问题似乎出在幻像模块上,无法与集群正常工作。如果你用一种测试替身替换它,比如

var phantom = {
    create: function (callback) {
        setImmediate(callback);
    }
};

你得到预期的全 2 输出。为了继续我的调查,我进行了修改node_modules/phantom/phantom.js以在您出现问题的地方进行最小设置。就是这个:

var http = require('http'), shoe = require('shoe'), spawn = require('win-spawn');

exports.create = function(cb) {
    var httpServer, sock;
    httpServer = http.createServer();
    httpServer.listen(0);
    httpServer.on('listening', function() {
        var listeningPort = httpServer.address().port;
        spawn('phantomjs', [].concat([__dirname + '/shim.js', listeningPort]));
    });
    sock = shoe(cb);
    return sock.install(httpServer, '/dnode');
};

这里发生的情况是启动了一个监听服务器,然后启动了一个 phantomjs 进程,该进程通过 WebSocket 连接到监听服务器,并对其进行写入,然后调用回调cb()。你可以通过观察shim.js和试验来获得这种理解。

那有什么问题!?好吧,如果您这样做console.log()listeningPort您将看到您获得相同的端口 8 次。所以看起来每次你调用时phantom.create(),你都会以某种方式重用同一个监听服务器,因此你的回调只在一个进程中被调用。

在尝试侦听端口 0 时,这似乎是您正在使用的 Node 版本的一种特殊行为。这也可以解释为什么使用另一个版本的 Node,问题没有发生(根据上面的评论)。这是我的一个要点,它隔离了这种反直觉的行为。

解决方案是在调用时指定一个端口phantom.create(),并使用 8 个不同的端口,例如,phantom.create(fn, { port: YOUR_PORT })在您的app.js.

于 2014-09-15T21:46:16.290 回答