一、概述
1、pm2是什么?
pm2是node进程管理工具。
2、为什么选它?与其他工具的对比
二、特性
1、后台运行
普通启动方式:node index.js,关闭终端就结束进程;
pm2可以后台运行,终端关闭不影响。
2、自动重启
可以监听某些文件改动,自动重启
3、停止不稳定的进程
限制不稳定的重启的次数,达到上限就停止进程。
4、0 秒停机重启
集群模式下,可以达到重启时不停止服务。
5、简单日志管理
pm2可以收集日志,并有插件配合进行管理。后面会提到。
6、自动负载均衡
cluster模式下,会自动使用轮询的方式达到负载均衡,从而减轻服务器的压力。
7、提供实时的接口
pm2插件提供实时的接口,返回服务器与进程的信息,后面会提到。
8、集成管理
对于多个进程,不同环境,可以统一配置,方便管理。
三、基础用法
1、启动进程: pm2 start app.js
app.js是node的启动文件,控制台会有如下打印。
(1)其中app name 和id都是这个进程的标识,可以对他们进行别的操作,比如stop,delete等。
(2)mode:进程模式,cluster或fork。cluster有多个进程,而fork只有一个。
(3)status:进程是否在线
(4)restart:重启次数
(5)uptime:运行时间
(6)cpu:cpu占用率
(7)mem:内存占用大小
2、停止进程:pm2 stop app_name|app_id|all
3、删除进程:pm2 delete app_name|app_id|all
4、重启进程:pm2 restart/reload app_name|app_id|all
集群模式下,restart中断服务,而reload不会
5、查看所有的进程:pm2 list/ls/status
id编号从1~4的是一个应用,分别对应4个进程。
6、查看某一个进程的信息:pm2 show app_name|app_id
第一张图是指进程的信息,比如status(状态)、restarts(重启次数)、uptime(运行时间)、script path(启动入口的路径)、script args(启动文件的参数)、error log path(错误日志的路径)、out log path(输出日志的路径)、exec mode(进程的模式)、watch&reload(是否开启监听文件变动重启)、unstable restarts(不稳定的重启次数)
第二张图是指代码指标:heap size(堆内存)、heap usage(堆内存使用率)、used heap size(堆内存使用情况)、event loop latency(事件循环时延)、event loop latency p95(事件循环时延 第95分位)
7、查看日志:pm2 logs
会打印下面的信息。但是一般不这么看,一般直接进入红框的路径,直接用less 命令查看日志文件。
8、监控所有进程:pm2 monit
左上角是进程的列举,右上角是全部的实时日志,左下角是选中进程的代码指标,右下角是进程的信息。
但是这样有2个不好的地方:
(1)不可能这样一直开着终端看监控
(2)比较容易死机
9、启动命令(start)还可以带参数
--name
给进程命名
--watch
是否开启自动重启--max-memory-restart
最大重启内存
--log
指定日志文件路径
-- arg1 arg2 arg3
其他参数
=========================================我是分割线==================================
- 小结:
上面介绍的这些启动其实有弊端:
1、通过命令行传递参数,无法记住到底传递过哪些参数。
2、对于多个进程,不方便管理。
请见下章的大招
四、集成部署(Ecosystem File)
1、why
(1)不同环境(dev、test、master)
(2)通过命令行传递参数不方便
(3) 同时管理多个应用
2、how
生成一个配置文件:pm2 ecosystem
app是要管理应用的数组,每个对象都是一个应用的配置。
module.exports = {
apps: [
{
name: "app",
script: './app.js',
env: {
NODE_ENV: "development",
},
evn_master: {
NODE_ENV: "master"
}
}
]
}
3、配置项
(1)基础类
name:进程名
script:node启动文件的路径
cwd :项目所在的目录
args :通过命令行传递给node启动文件的参数
interpreter :编译器的绝对路径(默认node)
interpreter_args :传给编译器的参数
node_args:传给node的参数
(2)进阶类
instances :进程数
exec_mode :进程的模式(cluster或fork)
- ps: cluster模式利用node的child_process模块孵化多个子进程,主进程监听端口,子进程只和主进程通信,从而
达到单个端口多个进程;通过轮转方式实现负载均衡。
watch :布尔值或文件数组,允许开启监听文件改动重启
ignore_watch :不监听的文件
max_memory_restart :超过该内存就自动重启
env :应用中的默认环境变量
env_ :命令行中可传入的环境变量,覆盖默认环境变量
source_map_support :默认true,支持sourcemap文件
(3)日志类
log_date_format :日志时间格式
error_file :错误日志存放路径
out_file :全部日志存放路径
combine_logs:是否将不同id的进程日志合并
merge_logs:同上
(4)控制流
min_uptime :pm2认为进程在线的最小时长
listen_timeout :如果app没有发送ready信号,间隔多长时间reload
kill_timeout :从告诉进程要关闭到强制关闭进程的间隔时间
wait_ready:是否等待进程发送ready信号
max_restarts :最大不稳定重启次数(不稳定指的是小于1s或者小于的min_uptime重启)
restart_delay:进程掉线后,等待多长时间重启
autorestart: 是否开启自动重启
其实还有一个 部署类,但是因为在我的场景中用不上,就没介绍,详细可以看官方文档。
4、m站最佳实践
-
pm2配置文件是一个单独的工程(pm2-server)
(1)配置踩坑经历:
a)script:若使用cluster模式,必须是启动文件入口,不可通过nuxt start启动
b) max_restarts:指不稳定重启,即小于1s或min_uptime的重启,要结合min_uptime配置才起效
c) listen_timeout:当cluster模式时,这个值要大于一个进程启动所需时间,否则reload时会造成短暂的服务不可用
踩坑经历:
(1)script:若使用cluster模式,必须是启动文件入口,不可通过npm启动
(2)max_restarts:指不稳定重启,即小于1s或min_uptime的重启,要结合min_uptime配置才起效
(3)listen_timeout:当cluster模式时,这个值要大于一个进程启动所需时间,否则reload时会造成短暂的服务不可用
(2)配置启动命令(package.json)
命令解释:
cross-env NODE_ENV=development pm2 start pm2-conf/ecosystem.config.js --only detective --env test
1、 cross-env NODE_ENV=development ,pm2-server工程的环境变量,目的是区分各个环境的应用启动路径
2、 pm2 start pm2-conf/ecosystem.config.js ,pm2的启动命令
3、 --only detective --env test ,传递给pm2的参数,-- only <name>,--env <env name>
(3)部署
前置条件:
pm2的ecosystem file单独作为一个工程(pm2-server),与其他工程一样的方法拷贝至服务器
m站构建流程:
1、jenkins从git上拉取代码
2、构建完,压缩拷贝至服务器
3、在服务器上切换至pm2-server目录,通过pm2命令启动m站 (npm run reloadM)
即:
cross-env NODE_ENV=master pm2 reload pm2-conf/ecosystem.config.js --only mweb --env master
五、Graceful start/shutdown
1、start
有时候需要等待进程与数据库或者其他建立起链接之后再启动,希望pm2等待这段时间再去启动进程。这个时候就要配置wait_ready: true;同时在进程准备好时发送process.send('ready')
var http = require('http');
var app = http.createServer(function(req, res) {
res.writeHead(200);
res.end('hey');
})
var listener = app.listen(0, function() {
console.log('Listening on port ' + listener.address().port);
// Here we send the ready signal to PM2
process.send('ready');
});
2、shutdown
(1)当restart/reload/stop进程时,pm2会向进程发送一个SIGINT信号,告诉进程将会被停止; *当进程接到pm2的SIGINT信号时,可以终止所有连接,清除所有任务,这样就可以【干净利索】的关闭进程
(2)如果进程1.6s内(参数:kill_timeout,默认1600ms)没有停止,pm2会发送一个SIGKILL信号,之后强制进程退出。
process.on('SIGINT', function() {
db.stop(function(err) {
process.exit(err ? 1 : 0);
});
});
六、pm2插件
1、pm2-logrorate
pm2只收集日志,通常可以配合pm2-logrotate插件来管理日志,如修改日志文件名,日志分割,日志文件数量管理,自动删除早期日志等。
2、pm2-web
pm2 服务状态监控程序,默认9615端口,返回该机器的信息,node进程的信息。
3、pm2.io
pm2的可视化实时监控(收费)
(1)服务器信息
(2)进程信息:重启次数,cpu使用率,内存占用,event loop延迟,报错邮件提醒等
四、自研监控
其实利用pm2-web,轮询它提供的接口,做一个可视化。展示图片就不放上来了。
主要观察指标:
- 进程状态:online
- 重启次数:一定范围
- 内存使用:稳定
- cpu占用率:稳定
- 平均负载:大于0.7有压力,持续大于1.2危险
结语:
其实有很多pm2功能还没有提到,因为自己没用到所以也没有去细究。有感兴趣的可以互相学习讨论。