Reputation: 3889
I'm using node
+ express
as my web server, and has a cluster
of 4 workers
.
I tried several ways to deliberately kill a worker
:
process.exit()
in a controller, and triggered using a browser action. Thought this is just for a single worker process, but turned out all workers were killed.
Again in a controller, I let a worker
send suicide announcement to the master
:
process.send('suicide');
and here goes my master process:
if (cluster.isMaster) {
console.log(`Master cluster setting up ${numWorkers} workers...`);
for (let i = 0; i < numWorkers; i++) {
const worker = cluster.fork();
worker.on('message', msg => {
console.log(worker.process.pid + ' wants to suicide');
worker.kill();
process.kill(worker.process.pid);
});
}
}
It turned out, worker.kill()
doesn't affect at all, and process.kill(worker.process.pid);
killing all 4 workers again. Also, the console.log
appeared 4 times which I don't understand. I used a browser to trigger some action that hence triggers the suicide announcement, shouldn't this be a single worker's behavior?
I'm also using WebSockets
in the projects and keeps a connection, don't know if this matters. Any help is appreciated!
EDIT:
Thanks for @Mia I found the reason: when I put process.exit()
in the else
statement(when cluster.isWorker
) it works fine, but when put in a specific controller, it turns out to affect all the workers. Don't know how to solve yet. Shouldn't the controller affect only one specific worker?
Upvotes: 0
Views: 3537
Reputation: 184
I am sorry to write here, I am unable to comment due to my reputation. I have written like the following and it works fine. first clusters are created and open servers, whenever a cluster gets a request app.get("/"), 2 seconds later it exits by process.exit method. you can confirm that this works well by printing out remaining workers.
'use strict';
const cluster = require('cluster');
const os = require('os');
if (cluster.isMaster) {
const cpus = os.cpus().length;
for (let i = 0; i < cpus; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code) => {
console.log(`${worker.process.pid} is killed`);
console.log("remaining wokers");
const workers = Object.keys(cluster.workers);
for(let worker of workers){
console.log(cluster.workers[worker].process.pid);
}
});
} else {
console.log("process id ",process.pid);
const express = require("express");
const app = express();
const path = require("path");
const fs = require("fs");
const http = require('http').Server(app);
const io = require('socket.io')(http);
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(express.static('public'));
app.get('/',function(req,res){
console.log("connected via" , process.pid);
setTimeout(()=>{
process.exit();
},2000)
res.sendFile(path.join(__dirname+"/public/view/index.html"));
});
http.listen(3000);
}
----------------------------code separated into modules---------------
Root (server.js)
'use strict';
const cluster = require('cluster');
const os = require('os');
if (cluster.isMaster) {
const cpus = os.cpus().length;
for (let i = 0; i < cpus; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code) => {
console.log(`${worker.process.pid} is killed`);
console.log("remaining wokers");
const workers = Object.keys(cluster.workers);
for(let worker of workers){
console.log(cluster.workers[worker].process.pid);
}
});
} else {
console.log("process id ",process.pid);
const express = require('./modules/express');
const http = require('http').Server(express);
http.listen(3000);
}
Express
const express = require("express");
const app = express();
const bodyParser = require('body-parser');
const route = require('../route');
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(express.static('public'));
route(app);
module.exports = app;
Route (index.js)
const HomeController = require('../controllers/HomeController');
module.exports = function(app){
app.get('/',HomeController.renderIndex);
app.get('/killProcess',HomeController.killProcess);
}
HomeController
const path = require('path');
exports.renderIndex = function(req,res){
console.log("connected via" , process.pid);
res.sendFile(path.join(__dirname+"/../public/view/index.html"));
}
exports.killProcess = function(req,res){
res.write(`current process ${process.pid} is killed`);
res.end();
process.kill(process.pid);
}
Client side (browser)
$("#kill").on("click",function(e){
$.ajax({
url:"/killProcess"
}).success(function(data){
console.log(data);
})
})
Upvotes: 3