众所周知,Nodejs是单线程运行的,这也是它经常被吐槽的一个点。针对这个点,Node推出了Cluster这个模块,用于创建多进程的Node应用。

基础使用

Cluster的基本使用方法就是cluster.fork(),这样就能直接创建一个新的进程。进程使用有完全独立的数据空间,堆栈等。这个时候我们就有疑问了,既然是这个效果,那么我们为什么不自己fork呢?

Cluster不仅仅是fork出一个进程而已,它还帮我们管理了子进程,有通信机制,还有负载均衡等等功能,这些功能要自己实现的话,需要花费大量的工作量。

并且提一点,Cluster并不是fork的越多越好,Cluster是为了让Node利用起CPU的多核而设计的,所以Cluster fork的数量最好不要超过CPU的核数:

let cpus = require("os").cpus().length;

for (let i = 0; i < cpus; i++) {
    cluster.fork()
}

上面的代码就是创建和CPU核数相同数量的Cluster,但是这个时候子进程并没有业务处理,稍微加工一下上面的代码,就能有更多的业务了:

let cluster = require('cluster');
let http = require('http');
let numCPUs = require("os").cpus().length;

if (cluster.isMaster) {
    for (let i = 0; i < numCPUs; i++) {
        cluster.fork();
    }
} else {
    http.createServer(function(req, res) {
        res.writeHead(200);
        res.end('process ' + process.pid + ' says hello!');
    }).listen(8000);
}

我们创建了多个web服务器实例,并且共用了8000这一个端口,在访问的接口的时候,Cluster会用自己的负载均衡算法,将请求交给子进程处理。

优点

最简单也是大家都能想到的一点,通过利用多核,Node的性能进一步的提高,这是一个对比的表格:

同时连接数 1 2 4 8 16
单进程 654 711 783 776 754
8进程 594 1198 2110 3010 3024

数据来自这里

还有一个显而易见的好处,就是可以做到零崩溃时间。因为在Cluster中的某个worker崩溃的时候,可以在Cluster的master中检测到,然后重启一个新的worker:

cluster.on('exit', function(worker, code, signal) {
    console.log('Worker ' + worker.process.pid + ' died with code: ' + code + ', and signal: ' + signal);
    console.log('Starting a new worker');
    cluster.fork();
});

改造量

单纯的评估改造量,要从代码写法和业务的角度来衡量,所以没办法统一评估。但我在这提到改造量,就是有其他的简洁改造方法。那就是PM2这个库。

PM2能够做到仅仅配置,而不需要改动我们的代码,就帮我们实现多进程启动。

安装了PM2之后,将启动程序的命令改为:pm2 start app.js -i 8,这样PM2就能用上CPU的8个核来跑我们的Node应用。PM2还有很多方便的命令,我就不一一介绍了,感兴趣的可以去这里了解。

那么,既然我们能直接使用PM2来直接实现多进程,还需要Cluster干什么呢?

疑问

因为PM2是不侵入我们的代码的,如果我们的业务需求有特殊性,就不能使用PM2了。

最典型的,就是有状态服务。

许多带有session的简单Node应用,在PM2的负载均衡下,很有可能出现session丢失的情况。还有一些socket应用,需要加入同一个房间,在同一个房间内存中共享了数据。这些应用都不能使用PM2,那么就需要我们自己使用Cluster来进行处理了。

总结

Cluster能给Node带来性能上很大的提升,让Node以前让人诟病的单线程也得到解决了。同时,Cluster的多核利用,也能让我们发挥想象力,把它用在其他地方,比如编译打包,比如大数据处理等,以后也许能写出更好用的库。

分类: 前端

2 条评论

吴彦祖 · 2017年12月21日 20:14

然而为什么 不自己启动几个子进程 负载均衡还不如用外部的

    xieisabug · 2017年12月23日 16:13

    因为那样还得自己做端口映射和负载均衡,而cluster或者pm2是全自动进行,不需要开发人员或者运维人员关心

回复 吴彦祖 取消回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用 * 标注