NodeJS应用部署之PM2(充分利用多核cpu)

  • 前言
  • 正文
  • 推荐资料
  • 附录:NodeJS学习网络资料整理
    • 1 从零开始 – 入门篇
    • 2 成为高手 – 进阶篇
    • 3 追根溯源 – 内核篇
    • 4 跨界应用 – 创造篇
    • 5 利剑在手 – 工具篇
    • 6 Web技术 – 应用篇

 

前言

首先,本篇主要讲述发生在项目实际部署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集群模块的源码。

  1. PM2的安装部署很简洁,也很简单,执行npm install pm2 -g ,pm2就顺利安装到本地或者服务器上。
  2. PM2的使用也很简单,以下是PM2的常用命令和注释。

$ pm2 start app.js              # 启动app.js应用程序

$ pm2 start app.js -i 4         # cluster mode 模式启动4个app.js的应用实例     # 4个应用程序会自动进行负载均衡

$ pm2 start app.js --name="api" # 启动应用程序并命名为 "api"

$ pm2 start app.js --watch      # 当文件变化时自动重启应用

$ pm2 start script.sh           # 启动 bash 脚本

$ pm2 list                      # 列表 PM2 启动的所有的应用程序

$ pm2 monit                     # 显示每个应用程序的CPU和内存占用情况

$ pm2 show [app-name]           # 显示应用程序的所有信息

$ pm2 logs                      # 显示所有应用程序的日志

$ pm2 logs [app-name]           # 显示指定应用程序的日志

$ pm2 stop all                  # 停止所有的应用程序

$ pm2 stop 0                    # 停止 id为 0的指定应用程序

$ pm2 restart all               # 重启所有应用

$ pm2 reload all                # 重启 cluster mode下的所有应用

$ pm2 gracefulReload all        # Graceful reload all apps in cluster mode

$ pm2 delete all                # 关闭并删除所有应用

$ pm2 delete 0                  # 删除指定应用 id 0

$ pm2 scale api 10              # 把名字叫api的应用扩展到10个实例

$ pm2 reset [app-name]          # 重置重启数量

$ pm2 startup                   # 创建开机自启动命令

$ pm2 save                      # 保存当前应用列表

$ pm2 resurrect                 # 重新加载保存的应用列表

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。NodeJS应用部署之PM2(充分利用多核cpu)_第1张图片

如上图二所示,我们执行 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实现模型

NodeJS应用部署之PM2(充分利用多核cpu)_第2张图片

代码demo

var cluster = require('cluster');

var numCPUs = require('os').cpus().length;

 

if (cluster.isMaster) {

  console.log('[master] ' "start master...");

 

  for (var i = 0; i < numCPUs; i++) {

     cluster.fork();

  }

 

  cluster.on('listening'function (worker, address) {

    console.log('[master] ' 'listening: worker' + worker.id + ',pid:' + worker.process.pid + ', Address:' + address.address + ":" + address.port);

  });

 

else if (cluster.isWorker) {

  require('app.js');

}

//app.js就是开启具体的业务逻辑了

 

//app.js具体内容

const net = require('net');

//自动创建socket

const server = net.createServer(function(socket) { //'connection' listener

  socket.on('end'function() {

    console.log('server disconnected');

  });

  socket.on('data'function() {

    socket.end('hello\r\n');

  });

});

//开启端口的监听

server.listen(8124, function() { //'listening' listener

  console.log('working')

});

 

还有几篇博客推荐:

  • 【译】 Node.js v0.12的新特性 -- Cluster模式采用Round-Robin负载均衡 
  •  Nodejs cluster模块深入探究

 

讨论完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学习网络资料整理

1 从零开始 – 入门篇

准备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应用为系统服务

2 成为高手 – 进阶篇

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实现

3 追根溯源 – 内核篇

解读Nodejs多核处理模块cluster

Nodejs创建HTTPS服务器

Nodejs异步异常处理domain

Nodejs加密算法库Crypto

Node.js缓冲模块Buffer

Node.js进程通信模块child_process

4 跨界应用 – 创造篇

Nodejs与R跨平台通信

tty.js打通浏览器与Linux的通道

用Highcharts轻松构建交互性图表

5 利剑在手 – 工具篇

RequireJS异步模块加载

Nodejs临时文件回收器reap

Nodejs异步流程控制Async

Async多任务时间管理

让Nodejs来管理定时任务later

wind.js助力异步编程

UnderscoreJS精巧而强大工具包

Commander写自己的Nodejs命令

Stylus让CSS也能编程

Browserify 跑在浏览器上的Node程序

Retry优雅的失败重试策略

用UglifyJS2合并压缩混淆JS代码

Marked高效的Markdown解析器

6 Web技术 – 应用篇

Hexo在github上构建免费的Web应用

Jekyll在github上构建免费的Web应用

用WebStorm编辑Markdown

30秒制作幻灯片 Cleaver

你可能感兴趣的:(随笔,学习记录,nodejs,cpu)