startNewNode(nodeID) { this.logger.info(`Starting ${nodeID} node...`); const worker = cluster.fork(); worker.nodeID = nodeID; worker.on("message", msg => this.workerMessageHandler(worker, msg)); worker.on("disconnect", () => { const idx = this.nodes.findIndex(node => node.worker == worker); if (idx != -1) { const node = this.nodes[idx]; this.nodes.splice(idx, 1); this.logger.info(`Node ${node.nodeID} stopped.`); this.removeNodeIDFromMetric(node.nodeID); } }); worker.send({ cmd: "start", nodeID }); this.nodes.push({ nodeID, worker }); }
worker.on('message', msg => { if (msg.cmd && msg.cmd == 'notifyRequest') { numReqs++; console.log("numReqs =", numReqs); } });
function addWebWorker() { //cluster.fork({web: 1}); webWorkers.push(cluster.fork({web: 1}).id); //Update thresholdCapability thresholdCapability = threshold * webWorkers.length; cluster.on('online', function(worker) { cluster.setMaxListeners(0); // https://github.com/joyent/node/issues/5108 cluster.workers[worker.id].on('message', messageHandler); }); }
Object.keys(cluster.workers).forEach((id) => { cluster.workers[id].on('message', messageHandler); });
/** * @private */ _createWorkers(){ const worker = cluster.fork(); const pid = worker.process.pid; this._logger.info({workerPid: pid}, 'create new worker'); this._workers[pid] = worker; worker.once('exit', () => { this._logger.info({workerPid: pid}, 'worker died. Restart'); delete this._workers[pid]; this._createWorkers(); }); worker.on('message', ({cmd}) => { switch(cmd){ case 'EADDRINUSE': this._logger.fatal({workerPid: pid}, 'fatal error'); setImmediate(process.exit); break; default: break; } }); }
cluster.fork().on('exit', (code) => { clusterDone = true if(masterDone){ process.exit(0); } });
function startWorkers(msg) { const worker = []; const removed = {}; const n = msg.n || nworkers; log('worker-controller host', cgrid.uuid); for (let i = 0; i < n; i++) { worker[i] = cluster.fork({wsid: msg.wsid, rank: i, puuid: cgrid.uuid}); } worker.forEach(function (w) { w.on('message', function (msg) { switch (msg.cmd) { case 'rm': if (msg.dir && !removed[msg.dir]) { removed[msg.dir] = true; child_process.execFile('/bin/rm', ['-rf', msg.dir]); } break; default: console.error('unexpected msg', msg); } }); }); }
//signal of workers restart process.on("SIGUSR2", () => { const workers = Object.keys(cluster.workers); console.log("workers: ", workers); //recursive function over workers const restartWorker = workerIndex => { if (workerIndex >= workers.length) return; const worker = cluster.workers[workers[workerIndex]]; console.log(`Stopping worker: ${worker.process.pid}`); worker.disconnect(); // disconnect task worker.on("exit", () => { if (!worker.exitedAfterDisconnect) return; // when the worker was disconnected we can start a new one const newWorker = cluster.fork(); newWorker.on("listening", () => { // once the new worker is listerning we can restart the next worker restartWorker(workerIndex + 1); }); }); }; restartWorker(0); });
// support hot reloading process.on('SIGUSR2', () => { console.log('HOT RELOAD INITIATED'); // for each worker, spin up a new worker and then kill // the old one once the new worker is up and listening var pids = Object.keys(cluster.workers); pids.forEach(pid => { // spin up the replacement let worker = cluster.fork(); // assign it to a currently running worker worker.predecessor = pid; // when the new worker is ready and listening, kill its predecessor worker.on('listening', () => cluster.workers[this.predecessor].kill('SIGUSR2')); }) });
worker.on('listening', address => { console.log(address); });