前言
首先,本篇主要讲述发生在项目实际部署NodeJS应用时遇到的多核CPU没有充分利用的实际问题。
其次,下列推荐有众多推荐文章,有说明如何在部署或者开发时充分利用多核CPU,提高应用性能及稳定系的解决思路和现有可行的技术解决方案。
最终,仅就我们这里讨论的部署NodeJS时充分利用CPU多核心问题,最有效的解决方案是通过PM2(Node应用管理器)进行线上部署
正文
前面我们有提到一个结论,部署NodeJS应用需要充分利用CPU多核心时,可以直接通过PM2(Node应用管理器)进行线上部署。
那么PM2是什么,通俗来说,PM2就是一个进程管理工具,它可以用管理你的node进程,并查看node进程的状态,当然也支持性能监控,进程守护,负载均衡等功能。
而它的主要特性如下:
-
内建负载均衡(使用 Node cluster 集群模块)
-
后台运行
-
0 秒停机重载
-
具有 Ubuntu 和 CentOS 的启动脚本
-
停止不稳定的进程(避免无限循环)
-
控制台检测
-
提供 HTTP API
-
远程控制和实时的接口 API(Nodejs 模块,允许和 PM2 进程管理器交互)
我们这里讨论暂不讨论PM2的其它特性,只说PM2 Clueter Mode。
The cluster mode allows networked Node.js applications (http(s)/tcp/udp server) to be scaled across all CPUs available, without any code modifications. This greatly increases the performance and reliability of your applications, depending on the number of CPUs available. Under the hood, this uses the Node.js cluster module such that the scaled application’s child processes can automatically share server ports. To learn more, see How It Works in the official Node.js documentation on the cluster module.
这段话是PM2 Cluster Mode的官网原文,其含义大致是说PM2的集群模式允许网络Node.js应用程序(http(s)/tcp/udp服务器)在所有可用的cpu上扩展,而不需要修改任何代码。这极大地提高了应用程序的性能和可靠性,这取决于可用cpu的数量。在底层,它使用Node.js集群模块,这样扩展后的应用程序的子进程可以自动共享服务器端口。最后告诉我们尽管用就是了,当然如果我们想了解更多信息怎么办,可以自己去官方Node.js文档查看Cluster集群模块的源码。
- PM2的安装部署很简洁,也很简单,执行npm install pm2 -g ,pm2就顺利安装到本地或者服务器上。
- PM2的使用也很简单,以下是PM2的常用命令和注释。
|
3. To enable the cluster mode, just pass the -i option : pm2 start app.js -i max
max means that PM2 will auto detect the number of available CPUs and run as many processes as possible.(max表示PM2将自动检测可用CPU的数量并运行尽可能多的进程)
这也是充分利用多核CPU的关键,让PM2按可用的CPU数量帮我们创建多个进程,在实际测试中,我发现PM2检测的可用CPU数量实际是服务器的CPU逻辑处理器数量,不同于CPU核心数。尽管逻辑处理器数量可以通过超线程技术实现两倍CPU核心数,不过毕竟计算资源还是只有一份,遇到两个线程都要使用同样的计算单元时,还是得要排队,还要花时间在两个线程之前的协调工作上,所以整体工作效率的根本没有2倍,绝大多数时候能提升个20%-30%就不错了。(一个核同时执行两个线程)
例:环境为一台4核cpu的ubuntu18的linux服务器,在singleCore.js所在目录下执行 pm2 start singleCore.js -i max后,可以查看到pm2当前为我们执行的nodejs应用创建了4个进程的cluster。
如上图二所示,我们执行 pm2 monit后,可以查看到pm2管理的每个nodejs应用的进程信息,此时可最大支持并发处理4个cpu密集型运算,当CPU密集型运算并发满时,CPU的4个线程都会满负荷进行运算,如果只有一个node进程时,只是只能接受到一个CPU密集型的运算请求,其他的都无法访问到node listen的端口,多进程好处高下立见。
以上,主要讨论是nodejs应用多核心cpu利用的一次实践,我们也提到了nodejs的cluster集群模块的设计是支持和实现nodejs应用实现利用多核CPU的关键所在,这里简单的讨论一下 nodejs的Cluster。nodejs老生常谈的特点是单线程,异步IO,事件循环。这里主要介绍Node的多进程技术,以及如何借助多进程方式来提升应用的可用性和性能。从严格意义上面来讲,Node并非真正的单线程架构,Node自身还有一定的I/O线程存在,这些I/O线程由底层libuv处理,这部分线程对于JavaScript开发者是透明的,只在C++扩展开发时才会关注到。JavaScript代码永远运行在V8上,是单线程的。现在围绕JavaScript部分展开,所以屏蔽底层细节的讨论。
推荐一篇生动介绍nodejs cluster进程分配演化过程的blog,贴一张结果图
round-robin 轮转算法的nodejs实现模型
代码demo
|
还有几篇博客推荐:
讨论完nodejs cluster 模块,我们可以通过自己cluster.fork() 不同的worker来实现咱们自己的业务,接下来我们主要是讨论一下PM2究竟是如何利用nodejs 的 cluster module实现负载均衡的,以及我们究竟需不需要自己去开发cluster模块,还是说就把多进程的管理交给pm2来完成,我们还是只负责开发业务逻辑的实现,让pm2帮我们管理node应用的运行维护和负载均衡。
推荐资料
0、深入浅出Nodejs(书籍)
1、通过Node.js的Cluster模块源码,深入PM2原理
5、NodeJS 充分利用多核CPU服务器处理高并发请求 (原文:一个前端工程师眼里的 NodeJS)
附录:NodeJS学习网络资料整理
1 从零开始 – 入门篇
Mongoose使用案例–让JSON数据直接入库MongoDB
nodejs分页设计配合bootstrap-paginator
Nginx反向代理Nodejs – log4js日志IP显示错误
2 成为高手 – 进阶篇
NPM下载出错 No compatible version found