深入理解NodeJS 多进程和集群

2020-06-17 07:02:20易采站长站整理


// 文件:server.js
const os = require("os"); // os 模块用于获取系统信息
const http = require("http");
const path = require("path");
const { fork } = rquire("child_process");

// 创建服务
const server = createServer((res, req) => {
res.end("hello");
}).listen(3000);

// 根据 CPU 个数创建子进程
os.cpus().forEach(() => {
fork("child_server.js", {
cwd: path.join(__dirname);
}).send("server", server);
});


// 文件:child_server.js
const http = require("http");

// 接收来自主进程发来的服务
process.on("message", (data, server) => {
http.createServer((req, res) => {
res.end(`child${process.pid}`);
}).listen(server); // 子进程共用主进程的服务
});

上面代码中由主进程处理的请求会返回 hello,由子进程处理的请求会返回 child 加进程的 pid 组成的字符串。

2、使用 cluster 实现集群

cluster 模块是 NodeJS 提供的用来实现集群的,他将 child_process 创建子进程的方法集成进去,实现方式要比使用 ipc 更简洁。


// 文件:cluster.js
const cluster = require("cluster");
const http = require("http");
const os = require("os");

// 判断当前执行的进程是否为主进程,为主进程则创建子进程,否则用子进程监听服务
if (cluster.isMaster) {
// 创建子进程
os.cpus().forEach(() => cluster.fork());
} else {
// 创建并监听服务
http.createServer((req, res) => {
res.end(`child${process.pid}`);
}).listen(3000);
}

上面代码既会执行 if 又会执行 else,这看似很奇怪,但其实不是在同一次执行的,主进程执行时会通过 cluster.fork 创建子进程,当子进程被创建会将该文件再次执行,此时则会执行 else 中对服务的监听,还有另一种用法将主进程和子进程执行的代码拆分开,逻辑更清晰,用法如下。


// 文件:cluster.js
const cluster = require("cluster");
const path = require("path");
const os = require("os");

// 设置子进程读取文件的路径
cluster.setupMaster({
exec: path.join(__dirname, "cluster-server.js")
});

// 创建子进程
os.cpus().forEach(() => cluster.fork());


// 文件:cluster-server.js
const http = require("http");

// 创建并监听服务
http.createServer((req, res) => {
res.end(`child${process.pid}`);
}).listen(3000);

通过 cluster.setupMaster 设置子进程执行文件以后,就可以将主进程和子进程的逻辑拆分开,在实际的开发中这样的方式也是最常用的,耦合度低,可读性好,更符合开发的原则。