深入浅析Node的进程管理工具“pm2”
本篇文章给大家分享Node的进程管理工具“pm2”,聊聊为什么需要pm2、安装和使用pm2的方法,希望对大家有所帮助!
PM2简介
PM2是一个内建了负载均衡器的node进程管理工具,可以利用它来简化很多node应用管理的繁琐任务,如性能监控、自动重启、负载均衡等,而且使用非常简单。当你要把你的独立代码利用全部的服务器上的所有 CPU,并保证进程永远都活着,0 秒的重载, PM2 是完美的。
PM2官网地址:https://pm2.keymetrics.io/docs/usage/quick-start/
为什么需要pm2?
目前Nodejs开发中有很多痛点,因为node本身是一个单线程应用,它的特点就是所有方法都是串行一次执行,并且node并没有能力像Java一样独自去创建一个新的线程来实现异步操作,如果在执行I/O中遇到了阻塞就会降低整个应用的执行效率,导致CPU使用率高等不利原因。【相关教程推荐:nodejs视频教程、编程教学】
因此在这种模式下,一个线程只能处理一个任务,要想提高吞吐量必须通过多线程。虽然单线程的好处有很多比如避免了线程同步或者死锁、状态同步等等之类的问题,但是在应用和计算能力要求日益倍增的今天,单线程最大的弊端就是无法利用多核CPU带来的优势来提升运行效率。pm2可以把你的应用部署到服务器所有的CPU上,有效的解决这个问题
特性
内建负载均衡(使用Node cluster 集群模块)
后台运行
0秒停机重载(维护升级的时候不需要停机).
具有Ubuntu和CentOS 的启动脚本
停止不稳定的进程(避免无限循环)
控制台检测
提供 HTTP API
远程控制和实时的接口API ( Nodejs 模块,允许和PM2进程管理器交互 )
安装
直接使用 npm 进行全局安装即可。当然你也可以使用 yarn 来进行安装
// npmnpm install -g pm2 // yarnyarn global add pm2登录后复制
基本命令
// 启动命令 pm2 start app.js // 启动nodeJs应用,进程的默认名称为文件名app pm2 start app.js--name mynode // 启动node,并指定进程名称为mynode pm2 start app.js - i max // 根据有效CPU数目启动最大进程数目 pm2 start app.js - i 3 // 启动3个进程 pm2 start app.js--watch // 实时监控的方式启动,app.js文件有变动时,pm2会自动reload pm2 start app.js - x // 用fork模式启动 app.js 而不是使用 cluster pm2 start app.js - x– - a 23 // 用fork模式启动 app.js 并且传递参数(-a 23) pm2 start app.json // 启动进程, 在app.json里设置选项 pm2 start app.js - i max– - a 23 // 在 – 之后给 app.js 传递参数 pm2 start app.js - i max - e err.log - o out.log // 启动并生成一个配置文件 // 查看与监视进程 pm2 list | pm2 ls // 显示所有进程; pm2 show 0 | pm2 info 0 // 查看进程id为0的详细信息 pm2 monit // 进入监视页面,监视每个node进程的CPU和内存的使用情况 // 停止、删除进程 pm2 stop 0 // 停止id为0的进程 pm2 stop all // 停止所有进程 pm2 delete 0 // 删除id为0的进程 pm2 delete all // 删除所有进程 // 重启、重载 pm2 restart 0 // 重启id为0的进程 pm2 restart all // 重启所有进程 pm2 reload 0 // 0秒停机重载id为0进程(用于 NETWORKED 进程) pm2 reload all // 重载所有进程 // 日志操作 pm2 logs // 显示所有进程的日志 pm2 logs 0 // 显示进程id为0的日志 pm2 flush // 清空所有日志文件 pm2 reloadLogs // 重载所有日志 pm2 startup // 产生init脚本,保持进程活着 // 杀死PM2进程 pm2 kill登录后复制
pm2使用方式
使用 pm2 主要有 2 种方式:命令行、配置文件。虽然使用配置文件的方式最终仍然需要使用命令行来启动,但两者的主要区别是:(1)命令行方式需要将各种配置参数在命令行中输入。(2)配置文件方式将各种配置参数放在了配置文件里面。
举个例子:你需要启动一个应用,并指定应用名称为 newApp,设定入口文件路径为 index.js ,我们来看看如何通过两种方式将应用名称和入口文件路径这两个参数带进去
【1】命令行方式
pm2 start index.js --name newApp登录后复制
【2】配置文件方式
首先我们需要创建一个配置文件(pm2.config.js),里面内容如下:
// 文件名为 pm2.config.js module.exports = { apps: [{ name: "newApp", // 应用名称 script: "./index.js" // 入口文件 }] }登录后复制
然后再在命令行输入以下内容,表明以指定的配置文件启动应用
pm2 start pm2.config.js登录后复制
【3】总结
通过对比以上两种形式,你可以看出:使用配置文件的方式,可以将各种参数、环境变量等内容 持久化 地保留在文件中,方便批量管理各种应用,避免在命令行中由于 遗忘、手误 等原因导致启动参数的不可控。
创建配置文件的方式
可以自行创建一个 Javascript 文件或者使用以下命令生成配置文件,需要注意的一点是,pm2 要求配置文件的文件名必须以 .config.js 结尾。
【1】命令生成
pm2 ecosystem登录后复制
命令生成的配置文件名称为ecosystem.config.js,格式如下, 可以发现这个文件就是导出 一个对象,其中有个 apps 属性,这是一个列表,其中的每一项都对应一个应用,在每一个子项的对象中设置对应应用的配置参数,你可以在配置文件中配置多个应用。
module.exports = { apps : [{ script: 'index.js', watch: '.' }, { script: './service-worker/', watch: ['./service-worker'] }], 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': '' } }};登录后复制
【2】自行创建
如果你自行创建 Javascript 文件,按照以上格式创建即可,注意文件名要以config.js结尾。
【3】注意
这个配置文件无论是通过命令创建或者你手工自己创建的,只要符合语法,两者是没有任何区别的。除了 .js 形式的配置文件外,pm2 还支持 .json 和 .yml 形式的配置文件,这三种配置文件的形式本质上没有任何区别,参数名称也完全一致,差异仅在于参数呈现的方式。
案例
我们先创建几个项目文件用于演示,目录结构如下,demo1目录存放的项目project1用命令行方式使用pm2,demo2目录存放的项目project2和project3用配置文件方式使用pm2, 三个项目都是node.js项目,index.js是非常基础的 Koa 项目入口文件,ecosystem.config.js是配置文件,各自的 node_modules 文件中只安装了 koa 框架
pm2 ├── demo1 └── project1 | ├── index.js | └── node_modules └── demo2 ├── ecosystem.config.js ├── project2 │ ├── index.js │ └── node_modules └── project3 ├── index.js └── node_modules登录后复制
入口文件index.js代码如下,三个项目的port分别为 8001、8002、8003
'use strict' const Koa = require('koa') const app = new Koa() const PORT = 8001 // 三个项目分别为 8001,8002,8003 app.use(ctx => { ctx.body = { NODE_ENV: process.env.NODE_ENV, url: ctx.url, port: PORT, } }) app.listen(PORT)登录后复制
配置文件ecosystem.config.js 代码如下
module.exports = { apps: [{ cwd: '../demo2/project2', name: 'project2', script: 'index.js', watch: ['.'] }, cwd: '../demo2/project3', name: 'project3', script: 'index.js', watch: ['.'] }] }登录后复制
【1】启动应用
命令行方式:pm2 start xxx.js
配置文件方式:pm2 start || pm2 start ecosystem.config.js
我们使用命令行方式启动project1应用,进入到project文件目录,运行pm2 start index.js命令,我们没有在命令中设定任何参数,pm2 会自动按照默认参数值进行执行。例如自动将入口文件的文件名index作为应用名称。几乎每一次命令执行完成后,pm2 都会显示一个应用列表(如下图所示),接着你就可以在网页中输入:localhost:8001查看project1项目
我们接着使用配置文件方式启动project2和project3应用,因为两个应用的配置在同一个文件,因此我们只需要运行一次配置文件,启动成功后可在网页中访问localhost:8002和localhost:8003
【2】停止应用
使用id停止:pm2 stop <id>
使用name停止:pm2 stop <name>
停止所有应用:pm2 stop all
【3】重启应用
使用id重启:pm2 reload <id>
使用name重启:pm2 reload <name>
重启所有应用:pm2 reload all
【4】显示应用列表
pm2 list
pm2 ls
pm2 status
【5】以JSON格式显示应用列表
pm2 jlist
pm2 prettylist
使用 pm2 jlist 命令,你会发现输出的内容很乱,你可以使用 pm2 prettylist 命令来输出优化过的 JSON 格式内容
【6】查看应用信息
pm2 describe id
pm2 describe name
上述的 JSON 格式应用列表,输出了所有应用的信息,而且信息十分凌乱,我们可以使用 pm2 describe 命令来查看指定应用的信息
【7】实时打印日志
打印日志:pm2 logs
指定日志行数:pm2 logs --lines (指定显示的日志行数)
清空日志:pm2 flush
对于线上正在运行的应用,有的时候需要打印实时日志来进行调试排查问题,虽然日志会自动添加到日志文件里面,但是总之不太方便。pm2 提供了logs命令,可以直接实时打印日志。
注意:当前命令行页面使用了该命令后,当前命令行会一直处于监听状态,你需要再新开一个命令行去敲其他命令
【8】显示仪表盘
pm2 monit
【9】删除应用
通过Id删除:pm2 delete id
通过name删除:pm2 delete name
删除所有应用:pm2 delete all
删除应用几乎不会造成任何后果,只是在管理列表中删除了这一项,并不会删除项目文件
【10】配置参数-应用名称
--name <app_name>
在命令行方式中,使用 --name <app_name> 参数指定应用名称,上面我们命令行运行的project1默认名称为index,现在我们指定名称为project1
【11】配置参数-监听目录
监听目录:--watch
指定目录不被监听:--ignore-watch
监听目录用于当指定监听目录文件发生变化时,pm2 将会自动重启应用
除了指定一个监听目录外,还可以再继续指定某个目录不被监听,例如上述的例子,指定了project1目录为监听目录,然后你把日志文件放在了这个目录下,比如为 logs 目录,这个目录不希望被监听,否则会形成死循环,这时候就需要用到另一个参数 --ignore-watch,输入一下命令
pm2 start 0 --watch --ignore-watch './logs'登录后复制
【12】配置参数-最大内存数
--max-memory-restart xxx(K|M|G)
设置最大内存数,当应用运行时占用的内存超出该数值后,应用将自动重启。命令行方式通过 --max-memory-restart 参数设定应用运行最大内存,后续跟上数值和单位,单位只能是 K,M,G 三个值,分别表示 KB,MB,GB 。
【13】配置参数-日志存放路径
--log <log_path>
日志默认会放置在 $HOME/.pm2/logs/ 目录下,使用 --log <log_path> 指定日志文件路径
pm2 start index.js --log ./logs/mylog.log登录后复制
更多node相关知识,请访问:nodejs 教程!