0

Я использую 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 

Почему фантомные экземпляры не привязаны к соответствующему работнику?

+0

Что происходит, если вы увеличиваете тайм-аут 'setInterval' до 10000 или 15000? Начало двух экземпляров может быть слишком медленным в течение 5 секунд или даже 10 секунд. –

+0

Все тот же результат :( – Deepsy

+0

Я бегу узел 0.10.26, и он работает – Maroshii

ответ

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. Что также объясняет, почему с другой версией узла проблема не возникала (согласно комментарию выше). Вот мой gist, который изолирует это противоинтуитивное поведение.

Решение состоит в том, чтобы указать порт при вызове phantom.create() и использовать 8 разных портов, например phantom.create(fn, { port: YOUR_PORT }), в вашем app.js.

+0

Отлично! Ты настоящий MVP! – Deepsy

 Смежные вопросы

  • Нет связанных вопросов^_^