详解Node.js Cluster(一)

作者: huip 发布时间: 2018-12-01

有过Node.js开发经验的小伙伴都知道,Node.js应用是运行在单线程上的单实例应用,这意味着Node.js默认情况下无法发挥多核系统的优势。通俗的说,如果你的计算机有8个CPU,如果你有一个应用通过node app.js来运行,将会只使用1个内核,那么其它的内核将被白白浪费。

值得庆幸的是,Node.js引入了 Cluster 模块来解决应用在多核运行的场景,从而最大化计算资源。

Cluster示例

Cluster模块能够很容易的创建一个能够共享服务器端口的多进程的服务端程序,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const cluster = require('cluster');
const http = require('http');
const 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`);
});
} else {
// Workers can share any TCP connection
// In this case it is an HTTP server
http.createServer((req, res) => {
res.writeHead(200);
res.end('hello world\n');
}).listen(8000);

console.log(`Worker ${process.pid} started`);
}

Cluster是如何工作的?

从上面的事例我们能看到,worker进程是通过child_process.fork()产生,因此worker和主节点可以通过IPC来相互通信。

cluster模块的两种分发模式

  1. 循环模式(round-robin)这是Node.js在除了windows系统以外的系统上默认采用的的模式。该模式的实现机制为,主进程监听某个计算机端口,主进程接收新的连接并且通过轮询的模式来分发给工作进程。Node.js通过内置的某些聪明的算法来解决单个工作进程过载的问题。
  2. master进程创建监听socket后发送给工作进程,然后工作进程直接接受连接。

通过以上两种模式的对比,理论上来说第二种模式会使最好的方案。但是根据使用结果观察来看,结果却不是很理想。由于操作系统调度的多变性,连接的分发常常是一种极不均衡的状态。在观察中有70%的请求分发给了8个进程中的2个。

总结

Node.js原生并不支持路由机制,因此在设计应用时,不能过度依赖内存数据对象,如session和login。

工作进程可以被杀死或者是由程序主动重建,由于工作进程运行时是绝对独立的,因此这些操作并不会影响其它的工作进程。只要有工作进程在运行中,服务就会一直接收新的请求并且持续服务。相反的,如果没有存活的工作进程,已经建立的连接将会被摧毁并且新产生的请求连接将会被拒绝。

Node.js并不会自动管理多个工作进程,这就需要编程人员根据自己的需求去管理工作进程池。

cluster模块主要适用于网络编程方向,但是对于其他需要工作进程的的场景依然适用。

参考资料

Node.js Cluster

如果你认为我的文章对你有帮助,欢迎点击上方按钮对我打赏

推荐阅读

详解CSS中的度量单位px|em|rem