首先,本篇主要讲述发生在项目实际部署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集群模块的源码。
|
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原理
2、nodejs高大上的部署方式(PM2)
3、Nodejs官方文档之worker_threads模块
4、Pm2官方文档之Cluster Mode
5、NodeJS 充分利用多核CPU服务器处理高并发请求 (原文:一个前端工程师眼里的 NodeJS)
6、NodeJS充分利用多核CPU以及它的稳定性
7、Node内部工作原理解析
准备Nodejs开发环境Ubuntu
Node.js开发框架Express4.x
Nodejs开发框架Express3.0开发手记–从零开始
Mongoose使用案例–让JSON数据直接入库MongoDB
Nodejs对MongoDB模糊查询
用Nodejs连接MySQL
Nodejs配合bootstrap-select下拉列表
nodejs分页设计配合bootstrap-paginator
nodejs豆瓣爬虫
玩转Nodejs日志管理log4js
Nginx反向代理Nodejs – log4js日志IP显示错误
upstart封装nodejs应用为系统服务
Nodejs基础中间件Connect
grunt让Nodejs规范起来
bower解决js的依赖管理
Yeoman自动构建js项目
快速创建基于npm的nodejs库
CNPM搭建私有的NPM服务
NPM下载出错 No compatible version found
Nodejs实现websocket的4种方式
Socket.io在线聊天室
websocket服务器监控
Nginx反向代理Websocket
restify构建REST服务
jasmine行为驱动,测试先行
Karma和Jasmine自动化单元测试
Nodejs服务器管理模块forever
Express结合Passport实现登陆认证
Passport现实社交网络OAuth登陆
Nodejs发邮件组件Nodemailer
快速排序的Nodejs实现
桶排序的Nodejs实现
解读Nodejs多核处理模块cluster
Nodejs创建HTTPS服务器
Nodejs异步异常处理domain
Nodejs加密算法库Crypto
Node.js缓冲模块Buffer
Node.js进程通信模块child_process
Nodejs与R跨平台通信
tty.js打通浏览器与Linux的通道
用Highcharts轻松构建交互性图表
RequireJS异步模块加载
Nodejs临时文件回收器reap
Nodejs异步流程控制Async
Async多任务时间管理
让Nodejs来管理定时任务later
wind.js助力异步编程
UnderscoreJS精巧而强大工具包
Commander写自己的Nodejs命令
Stylus让CSS也能编程
Browserify 跑在浏览器上的Node程序
Retry优雅的失败重试策略
用UglifyJS2合并压缩混淆JS代码
Marked高效的Markdown解析器
Hexo在github上构建免费的Web应用
Jekyll在github上构建免费的Web应用
用WebStorm编辑Markdown
30秒制作幻灯片 Cleaver