1、pm2是什么?
pm2是node进程管理工具。
2、为什么选它?与其他工具的对比
对比图
普通启动方式:node index.js,关闭终端就结束进程;
pm2可以后台运行,终端关闭不影响。
可以监听某些文件改动,自动重启
限制不稳定的重启的次数,达到上限就停止进程。
集群模式下,可以达到重启时不停止服务。
pm2可以收集日志,并有插件配合进行管理。后面会提到。
cluster模式下,会自动使用轮询的方式达到负载均衡,从而减轻服务器的压力。
pm2插件提供实时的接口,返回服务器与进程的信息,后面会提到。
对于多个进程,不同环境,可以统一配置,方便管理。
ps:这里补充一个安装方法:
npm install pm2 -g
如果这时候还是无法运行可以将node安装目录里面的bin目录里面的快捷方式链接到运行目录就可以了,具体操作方法:
whereis pm2
得到的目录就是pm2所在的目录,然后加一个快捷:
ln -s /usr/software/nodejs/bin/pm2 /usr/local/bin/
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:内存占用大小
集群模式下,restart中断服务,而reload不会
所有进程
id编号从1~4的是一个应用,分别对应4个进程。
第一张图是指进程的信息,比如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分位)
会打印下面的信息。但是一般不这么看,一般直接进入红框的路径,直接用less 命令查看日志文件。
左上角是进程的列举,右上角是全部的实时日志,左下角是选中进程的代码指标,右下角是进程的信息。
但是这样有2个不好的地方:
(1)不可能这样一直开着终端看监控
(2)比较容易死机
其它可用选项:
--watch
以监听模式启动,当文件发生变化时自动重启--max-memory-restart <200MB>
设置应用重载占用的最大内存--log
指定日志文件-- arg1 arg2 arg3
给启动脚本传递额外的参数--restart-delay
延时 x 毫秒自动重启--time
日志里添加时间前缀--no-autorestart
不自动重启--cron
按指定的定时任务规则强制重启--no-daemon
以非守护进程模式启动请见下章的大招
(1)不同环境(dev、test、master)
(2)通过命令行传递参数不方便
(3) 同时管理多个应用
生成一个配置文件:pm2 ecosystem
app是要管理应用的数组,每个对象都是一个应用的配置。
module.exports = {
apps: [
{
name: "app",
script: './app.js',
env: {
NODE_ENV: "development",
},
evn_master: {
NODE_ENV: "master"
}
}
]
}
(1)基础类
name:进程名
script:node启动文件的路径
cwd :项目所在的目录
args :通过命令行传递给node启动文件的参数
interpreter :编译器的绝对路径(默认node)
interpreter_args :传给编译器的参数
node_args:传给node的参数
(2)进阶类
instances :进程数
exec_mode :进程的模式(cluster或fork)
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: 是否开启自动重启
其实还有一个 部署类,但是因为在我的场景中用不上,就没介绍,详细可以看官方文档。
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 ,--env
(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
有时候需要等待进程与数据库或者其他建立起链接之后再启动,希望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');
});
(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只收集日志,通常可以配合pm2-logrotate插件来管理日志,如修改日志文件名,日志分割,日志文件数量管理,自动删除早期日志等。
pm2 服务状态监控程序,默认9615端口,返回该机器的信息,node进程的信息。
pm2的可视化实时监控(收费)
(1)服务器信息
(2)进程信息:重启次数,cpu使用率,内存占用,event loop延迟,报错邮件提醒等
其实利用pm2-web,轮询它提供的接口,做一个可视化。展示图片就不放上来了。
主要观察指标:
其实有很多pm2功能还没有提到,因为自己没用到所以也没有去细究。有感兴趣的可以互相学习讨论。
$ pm2 start app.js # 启动app.js应用程序
$ pm2 start app.js -i 4 # cluster mode 模式启动4个app.js的应用实例
$ 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 id# 显示应用程序的所有信息
$ pm2 logs # 显示所有应用程序的日志
$ pm2 logs id # 显示指定应用程序的日志
$ pm2 stop all # 停止所有的应用程序
$ pm2 stop 0 # 停止 id为 0的指定应用程序
$ pm2 restart all # 重启所有应用
$ pm2 reload all # 重启 cluster mode下的所有应用
$ pm2 delete all # 关闭并删除所有应用
$ pm2 delete 0 # 删除指定应用 id 0
$ pm2 gracefulReload all # Graceful reload all apps in cluster mode
$ 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 start app.js --node-args="--max-old-space-size=1024"
pm2 reset PID //一次只能重置一个
查看
# 查看所有已启动应用的基本信息
# 同 pm2 ls 或 pm2 status
$ pm2 list
# 查看所有应用的日志(历史 + 实时)
$ pm2 logs
$ pm2 logs www # 只查看应用 www 的日志
$ pm2 logs --lines 10 # 查看最后10条历史,默认 15 条
$ pm2 logs --timestamp # 实时日志添加时间前缀
$ pm2 logs www --lines 10 --err # 只查看应用 www 的最新 10 条错误日志
$ pm2 flush # ❗️清空所有日志文件
# 查看进程详情
$ pm2 show app_name|app_id
# 查看每个应用的CPU和内存资源实时占用情况
$ pm2 monit
# 在线的 Web 诊断系统,跨服务器
# 需要注册登录或使用 Github、Google 账户授权登录
$ pm2 monitor
管理应用状态
# 重启 ❗️
# 同时杀死并重启所有进程,短时间内服务不可用。
# 生成环境推荐使用 reload
$ pm2 restart app_id|app_name|all
# 重载
# 始终保持一个进程在线,避免宕机
$ pm2 reload app_id|app_name|all
# 停止
$ pm2 stop app_id|app_name|all
# 关闭并删除
$ pm2 delete app_id|app_name|all
# 直接杀死 pm2 守护进程
$ pm2 kill
静态服务器
# 将目录 dist 作为静态服务器根目录,端口为 3333
$ pm2 serve ./dist 3333
集群模式(自动负载均衡)
# max 表示 PM2 将自动检测可用 CPU 的数量并运行尽可能多的进程
# max 可以自定义,如果是 4 核 CPU,设置为 2 则只占用 2 核
pm2 start app.js -i max
开机自启动
$ pm2 startup
$ pm2 unstartup
应用列表
# 保存当前应用列表,以后可以恢复
$ pm2 save # 同 pm2 dump
# 重新加载之前保存的应用列表
$ pm2 resurrect
# 清除保存的应用列表
$ pm2 cleardump
配置文件
生成示例配置文件
$ pm2 ecosystem # 或 pm2 init
示例配置如下(根据实际项目需要添加、删除配置项)
module.exports = {
apps : [{
name : 'demo', // 应用名
script : 'app.js', // 应用文件位置
env: {
PM2_SERVE_PATH: ".", // 静态服务路径
PM2_SERVE_PORT: 8080, // 静态服务器访问端口
NODE_ENV: 'development' // 设置开发环境运行时
},
env_production : {
NODE_ENV: 'production' // 设置生产环境运行时
},
instances: "max", // 将应用程序分布在所有CPU核心上,可以是整数或负数
watch: true, // 监听模式
output: './out.log', // 指定日志标准输出文件及位置
error: './error.log', // 错误输出日志文件及位置
merge_logs: true, // 集群情况下,可以合并日志
log_type: "json", // 日志类型
log_date_format: "DD-MM-YYYY", // 日志的日期格式
}],
deploy : {
production : {
user : 'SSH_USERNAME',
host : 'SSH_HOSTMACHINE',
ref : 'origin/master',
repo : 'GIT_REPOSITORY',
path : 'DESTINATION_PATH',
'pre-deploy-local': '',
'post-deploy' : 'npm install && pm2 reload ecosystem.config.js --env production',
'pre-setup': ''
}
}
}
以配置文件启动示例
$ pm2 start ecosystem.config.js --env production
⚠️ 注意:配置文件支持 js 和 yaml 格式,还有一些没有列举的参数项,详见官方文档:https://pm2.keymetrics.io/docs/usage/application-declaration
升级 PM2
# 更新前推荐先保存当前应用列表,方便更新后直接恢复
$ pm2 save
# 更新主程序
$ npm install pm2 -g
# 紧接着更新内存中的程序
$ pm2 update
# 恢复应用列表
$ pm2 resurrect
日志切割
安装 pm2-logrotate-ext
扩展模块
项目地址:https://github.com/Lujo5/pm2-logrotate-ext
$ pm2 install pm2-logrotate-ext
重新启动应用后,pm2-logrotate-ext
以模块的形式被加载、启动。
可以通过以下命令对其配置进行修改:
# 当文件大小超过此设置则执行切割
$ pm2 set pm2-logrotate-ext:max_size 1M
# 保留最新的几个日志文件
$ pm2 set pm2-logrotate-ext:retain 30
# 是否开启 gzip 压缩
$ pm2 set pm2-logrotate-ext:compress false
# 文件名的日期部分格式
$ pm2 set pm2-logrotate-ext:dateFormat YYYY-MM-DD_HH-mm-ss
# 几秒钟检查一次日志文件大小
$ pm2 set pm2-logrotate-ext:workerInterval 30
# 类似于系统的定时任务,当满足指定规则时,
# 不管日志文件大小是否达到设置的最大值,直接对日志文件进行切割
$ pm2 set pm2-logrotate-ext:rotateInterval 0 0 * * *
# 对 pm2 模块产生的日志同样进行切割处理
$ pm2 set pm2-logrotate-ext:rotateModule true
# 是否按定时任务设置规则强制执行
# 如果设置为否,则只有当日志文件大小超过设置时才进行切割
$ pm2 set pm2-logrotate-ext:forced true