节点集群不会在适当的工作程序中生成幻像实例

时间:2014-09-12 02:03:01

标签: node.js phantomjs cluster-computing child-process node-cluster

我使用NodeJS和PhantomJS。我的目标是创建具有节点集群的4x节点实例,每个实例具有2个幻像子节点。我的代码看起来像这样:

cluster.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

为什么幻影实例没有附加到合适的工作人员身上?

1 个答案:

答案 0 :(得分: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时,问题并未发生(根据评论 以上)。这是我的gist,它隔离了这种反直觉的行为。

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