关于 Nodejs cluster 的问题(用自带的 cluster)
关于 Nodejs cluster 的问题(用自带的 cluster)
var cluster = require(‘cluster’); var http = require(‘http’); var numCPUs = require(‘os’).cpus().length;
// 获取 CPU 的数量 var workers = {}; if (cluster.isMaster) { console.log(‘master…’); // 初始化 CPU 数量相同的工作进程 for (var i = 0; i < numCPUs; i++) { var worker = cluster.fork(); workers[worker.pid] = worker; }
// 主进程分支
cluster.on('death', function (worker) {
// 当一个工作线程结束时,重新启动一个工作线程
delete workers[worker.pid];
worker = cluster.fork();
workers[worker.pid] = worker;
});
} else { // 工作進进程分支,启动服务器 console.log(‘worker----’);
http.createServer(function(req, res){
console.log('%s %s', req.method, req.url);
var body = 'Hello World';
res.writeHead(200, { 'Content-Length': body.length });
res.end(body);
}).listen(9000);
}
// 当主进程终止时,关闭所有工作进程 process.on(‘SIGTERM’, function () { for (var pid in workers) { process.kill(pid); } process.exit(0); });
================================ 以上代码,按设计应该是输出:'Hello World’ 但并没有输出,只在启动的时候输出了: master… worker---- worker---- worker---- worker---- worker---- worker---- worker---- worker----
在页面上访问,没有任何反应,最后页面访问失败;
============================================================
而下面这个代码就可以正常访问(把createServer放在前面),输出的结果也对,但用AB压了一下,发现用 1个子进程跟8个子进程基本上没有任何区别!
( 求解啊,这是为啥呢,是上面的程序哪里写的不对? 还是下面的代码还是相当于只用了一个子进程来处理请求?);
cup: 8核; 并发: 1000次 总请求:2000次
var cluster = require(‘cluster’); var http = require(‘http’); var numCPUs = require(‘os’).cpus().length;
http.createServer(function(req, res){ console.log(’%s %s’, req.method, req.url); var body = ‘Hello World’; res.writeHead(200, { ‘Content-Length’: body.length }); res.end(body); }).listen(9000);
// 获取 CPU 的数量 var workers = {}; if (cluster.isMaster) { console.log(‘master…’); // 初始化 CPU 数量相同的工作进程 for (var i = 0; i < numCPUs; i++) { var worker = cluster.fork(); workers[worker.pid] = worker; }
// 主进程分支
cluster.on('death', function (worker) {
// 当一个工作线程结束时,重新启动一个工作线程
delete workers[worker.pid];
worker = cluster.fork();
workers[worker.pid] = worker;
});
} else { // 工作進进程分支,启动服务器 console.log(‘worker----’);
}
// 当主进程终止时,关闭所有工作进程 process.on(‘SIGTERM’, function () { for (var pid in workers) { process.kill(pid); } process.exit(0); });
关于 Node.js Cluster 模块的问题
问题描述
在使用 Node.js 的 cluster
模块时,我们期望通过多进程的方式来提高应用的并发处理能力。然而,在实际操作中,无论是将 createServer
放在主进程中还是工作进程中,都发现多进程的效果并不明显。
示例代码分析
首先,我们来看一下原始代码:
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;
// 获取 CPU 的数量
var workers = {};
if (cluster.isMaster) {
console.log('master...');
// 初始化 CPU 数量相同的工作进程
for (var i = 0; i < numCPUs; i++) {
var worker = cluster.fork();
workers[worker.pid] = worker;
}
// 主进程分支
cluster.on('death', function (worker) {
// 当一个工作线程结束时,重新启动一个工作线程
delete workers[worker.pid];
worker = cluster.fork();
workers[worker.pid] = worker;
});
} else {
// 工作进程分支,启动服务器
console.log('worker----');
http.createServer(function(req, res) {
console.log('%s %s', req.method, req.url);
var body = 'Hello World';
res.writeHead(200, { 'Content-Length': body.length });
res.end(body);
}).listen(9000);
}
// 当主进程终止时,关闭所有工作进程
process.on('SIGTERM', function () {
for (var pid in workers) {
process.kill(pid);
}
process.exit(0);
});
问题所在
-
createServer
放在主进程中:如果将createServer
放在主进程中,那么所有的请求都会被主进程处理,而不会分发到各个工作进程中。这会导致多进程的优势无法体现出来。 -
createServer
放在工作进程中:如果将createServer
放在每个工作进程中,那么每个工作进程都会监听同一个端口,这会导致冲突。正确的做法是让主进程监听端口,并将连接分发给各个工作进程。
解决方案
以下是修正后的代码示例:
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
console.log(`Master ${process.pid} is running`);
// Fork workers.
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`Worker ${worker.process.pid} died`);
});
// Listen on a port and distribute requests to workers
const server = http.createServer((req, res) => {
console.log(`Request received by master: ${req.url}`);
res.writeHead(200);
res.end('Hello World');
});
server.listen(9000, () => {
console.log('Server listening on port 9000');
});
} else {
// Workers can share any TCP connection
// In this case it is an HTTP server
console.log(`Worker ${process.pid} started`);
http.createServer((req, res) => {
console.log(`Request received by worker ${process.pid}: ${req.url}`);
res.writeHead(200);
res.end('Hello World');
}).listen(9000);
}
关键点解释
-
主进程监听端口:主进程负责创建 HTTP 服务器并监听端口。这样可以确保请求能够被正确地分发到各个工作进程中。
-
工作进程处理请求:每个工作进程创建自己的 HTTP 服务器实例,但它们不直接监听端口。而是由主进程将请求转发到这些工作进程。
-
请求分发:Node.js 会自动将请求分发到不同的工作进程,从而实现负载均衡。
通过这种方式,你可以充分利用多核 CPU 的优势,提高应用的并发处理能力。
原因是:if (cluster.isMaster) 它一直为真,所以就没有运行到 http.createServer, 如果不是把http.createServer 放在第一行的话;
可是这是为什么呢? 难道网上的示例都是没有经过自己手动跑过的?
我找到问题了!@!~
是我自己的问题, sorry~