使用例子
为了让node应用能够在多核服务器中提高性能,node提供cluster
API,用于创建多个工作进程,然后由这些工作进程并行处理请求。
// master.js
const cluster = require('cluster');
const cpusLen = require('os').cpus().length;
const path = require('path');
console.log(`主进程:${
process.pid}`);
cluster.setupMaster({
exec: path.resolve(__dirname, './work.js'),
});
for (let i = 0; i < cpusLen; i++) {
cluster.fork();
}
// work.js
const http = require('http');
console.log(`工作进程:${
process.pid}`);
http.createServer((req, res) => {
res.end('hello');
}).listen(8080);
上面例子中,使用cluster
创建多个工作进程,这些工作进程能够共用8080
端口,我们请求localhost:8080
,请求任务会交给其中一个工作进程进行处理,该工作进程处理完成后,自行响应请求。
端口占用问题
这里有个问题,前面例子中,出现多个进程监听相同的端口,为什么程序没有报端口占用问题,由于socket套接字监听端口会有一个文件描述符,而每个进程的文件描述符都不相同,无法让多个进程都监听同一个端口,如下:
// master.js
const fork = require('child_process').fork;
const cpusLen = require('os').cpus().length;
const path = require('path');
console.log(`主进程:${
process.pid}`);
for (let i = 0; i < cpusLen; i++) {
fork(path.resolve(__dirname, './work.js'));
}
// work.js
const http = require('http');
console.log(`工作进程:${
process.pid}`);
http.createServer((req, res) => {
res.end('hello');
}).listen(8080);
当运行master.js
文件的时候,会报端口被占用的问题(Error: listen EADDRINUSE: address already in use :::8080
)。
我们修改下,只使用主进程监听端口,主进程将请求套接字发放给工作进程,由工作进程来进行业务处理。
// master.js
const fork = require('child_process').fork;
const cpusLen = require('os').cpus().length;
const path = require('path');
const net = require('net');
const server = net.createServer();
console.log(`主进程:${
process.pid}`);
const works = [];
let current = 0
for (let i = 0; i < cpusLen; i++) {
works.push(fork(path.resolve(__dirname, './work.js')));
}
server.listen(8080, () => {
if (current > works.length - 1) current = 0
works[current++].send('server', server);
server.close();
});
// work.js
const http = require('http');
const server = http.createServer((req, res) => {
res.end