PM2

使用pm2方便开启node集群模式

介绍

单个 Node.js 实例运行在单个线程中。

Node.js是一个运行在名叫V8的JavaScript引擎的平台系统。

V8本身是单线程运行的,并没有充分利用多核系统能力。(注:Node执行JS代码运行在V8上,是单线程,但并非真正的单线程架构)

为了充分利用多核系统,有时需要启用一组 Node.js 进程去处理负载任务。

Node.js的集群模式

Node.js提供了集群模块,简单讲就是复制一些可以共享TCP连接的工作线程。

工作原理

集群模块会创建一个master主线程,然后复制任意多份程序并启动,这叫做工作线程。

工作线程通过 IPC 频道进行通信并且使用了 Round-robin algorithm 算法进行工作调度以此实现负载均衡。

Round-robin调度策略主要是master主线程负责接收所有的连接并派发给下面的各个工作线程。

常见的例子

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(`主进程 ${process.pid} 正在运行`);

// 衍生工作进程。
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}

cluster.on('exit', (worker, code, signal) => {
console.log(`工作进程 ${worker.process.pid} 已退出`);
});
} else {
// 工作进程可以共享任何 TCP 连接。
// 在本例子中,共享的是 HTTP 服务器。
http.createServer((req, res) => {
res.writeHead(200);
res.end('你好世界\n');
}).listen(8000);

console.log(`工作进程 ${process.pid} 已启动`);
}

运行代码,则工作进程会共享 8000 端口:

$ node server.js
主进程 3596 正在运行
工作进程 4324 已启动
工作进程 4520 已启动
工作进程 6056 已启动
工作进程 5644 已启动

当然,你可以不受CPU核心限制的创建任意多个工作线程。

使用原生方法有些麻烦而且你还需要处理如果某个工作线程挂掉了等额外的逻辑。 (注:通过fork()复制的进程都是独立的进程,有着全新的V8实例)

pm2 的方式

pm2 内置了处理上述的逻辑,你不用再写这么多繁琐的代码了。

只需这样一行:

pm2 start app.js -i 4

-i <number of workers> 表示实例程序的个数。就是工作线程。s

如果 i 为0表示,会根据当前CPU核心数创建。

保持你的程序不中断运行

如果有任何工作线程意外挂掉了,PM2会立即重启他们。

当然你可以在任何时候重启,只需:

pm2 restart all

实时调整集群数量

你可以使用命令 pm2 scale <app name> <n> 调整你的线程数量。

pm2 scale app_name +3  // 会在当前基础上加3个工作线程。

在生产环境让你的程序永不中断

pm2 reload <app name> 命令会一个接一个的重启工作线程,在新的工作线程启动后才结束老的工作线程。

这种方式可以保持你的Node程序始终是运行状态。

即使在生产环境下部署了新的代码补丁。

也可以使用gracefulReload命令达到同样的目的,它不会立即结束工作线程,而是通过IPC向它发送关闭信号,这样它就可以关闭正在进行的连接,还可以在退出之前执行一些自定义任务。这种方式更优雅。

1
2
3
4
5
6
7
8
process.on('message', function(msg) {  
if (msg === 'shutdown') {
close_all_connections();
delete_cache();
server.close();
process.exit(0);
}
});

RPC

聊聊 Node.js RPC

卸载 pm2

npm uninstall pm2 -g

pm server
/Users/lqmeta/.npm-global/bin/pm2

1、
pm2 start /Users/lqmeta/Documents/project/mock-server/app.js –name=mock-server-3001
2、
cd /Users/lqmeta/Documents/project/userCenter/user-center
pm2 start npm –name=user-center-3000 – run dev
3、
sudo nginx
http://wemeet-dev.oa.com/user-center
4、
cd /Users/lqmeta/Documents/source/my/lqmeta.github.io
pm2 start npm –name=lqmeta-4000 – run draft

7、
cd /Users/lqmeta/Documents/project/embededPages
pm2 start npm –name=lqmeta-4000 – run draft

5、
cd /Users/lqmeta/Documents/source/react/my-app
pm2 start npm –name=my-app-3002 – run dev
6、
w2 start
http://10.64.40.73:8899

pm2 指令:

pm2 delete app 或 pm2 delete 0    删除;
pm2 list    查看; 
pm2 stop app_name|app_id  停止;
pm2 restart app_name|app_id  重启;
pm2 describe 0 查看某个进程的信息      pm2 show 0
pm2 logs 查看日志;   pm2 logs 0
pm2 monit  监控-查看进程资源消耗

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 flush


$ 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                 # 重新加载保存的应用列表

$ pm2 update                    # Save processes, kill PM2 and restore processes

$ pm2 generate                  # Generate a sample json configuration file


$ pm2 deploy app.json prod setup    # Setup "prod" remote server

$ pm2 deploy app.json prod          # Update "prod" remote server

$ pm2 deploy app.json prod revert 2 # Revert "prod" remote server by 2


$ pm2 module:generate [name]    # Generate sample module with name [name]

$ pm2 install pm2-logrotate     # Install module (here a log rotation system)

$ pm2 uninstall pm2-logrotate   # Uninstall module

$ pm2 publish                   # Increment version, git push and npm publish

目录介绍

pm2安装好后,会自动创建下面目录:

$HOME/.pm2 will contain all PM2 related files
$HOME/.pm2/logs will contain all applications logs
$HOME/.pm2/pids will contain all applications pids
$HOME/.pm2/pm2.log PM2 logs
$HOME/.pm2/pm2.pid PM2 pid
$HOME/.pm2/rpc.sock Socket file for remote commands
$HOME/.pm2/pub.sock Socket file for publishable events
$HOME/.pm2/conf.js PM2 Configuration