为什么要写这篇文章
最近利用ant-design-pro结合koa2搭建了一套后台管理系统,用于管理个人项目。由于需要将koa2代码部署到服务器上,很自然地就想到了用pm2来发布和管理。其实自己之前是有在工作中使用pm2的,但是我都是在别人搭建好的环境下进行使用,没有很好地领会精髓。在这次部署个人项目的实践中,自己从头到尾把控整个部署流程,所以收获是有很多的,因此才会准备写这篇文章,将自己的所学所知整理成文,既方便自己以后进行回顾,也可以帮助想要了解这块知识的朋友。
初识pm2
首先,我们要知道pm2是什么。pm2是一个node应用的监控管理工具,具有如下的功能:
- 以守护进程的方式将我们的node应用运行在后台
- 提供简便的方式启动或停止node应用
- 监控node应用的运行状态,并提供当node应用崩溃时自动重启的功能(不用手动
node app.js
啦) - 开启cluster模式后,会采用负载均衡的策略将node应用跑在多个cpu上,从而充分发挥多核cpu的性能
- 配合ecosystem.config.js,可以方便地进行一键部署
pm2常用的命令如下:
# Fork mode
pm2 start app.js --name my-app #启动一个node应用,并将其命名为my-app
# Cluster mode
pm2 start app.js -i 0 # 启动一个node应用,并开启cluster模式,使用的cpu数量取决于主机cpu的可用核数
pm2 start app.js -i max # 跟上述命令效果一致,不推荐使用
# Listing
pm2 list # 以表格的形式列出当前所有node应用的信息
pm2 jlist # 以原生JSON的形式列出当前所有node应用的信息
pm2 prettylist # 以美化过的JSON形式列出当前所有node应用的信息
pm2 describe 0 # 列举出id为0的应用的所有信息
# Logs
pm2 logs [--raw] # 以流的形式列举出所有node应用的日志
pm2 flush # 清空所有日志文件
pm2 reloadLogs # 重载所有日志文件
# Actions
pm2 stop all # 停止所有node应用
pm2 restart all # 重启所有node应用
pm2 reload all # 重载所有node应用,与restart不同的是这种方式可以实现不停机更新的效果
pm2 stop 0 # 停止id为0的node应用
pm2 restart 0 # 重启id为0的node应用
pm2 delete 0 # 删除id为0的node应用,pm2 list上就不会再出现了
pm2 delete all # 删除所有node应用
复制代码
使用pm2部署node应用
除了上述直接在命令行中操作pm2,更常见的使用方式是使用约定的配置文件(ecosystem.config.js)来管理。通过这个文件,我们可以简单高效的管理和发布多个node应用,下面将列出常见的配置:
module.exports = {
//apps是个数组,里面可以存放多个node应用实例的配置
apps : [{
name: 'my-app1', //指定node应用的名称
script: './src/index1.js', //指定node应用的入口文件
exec_mode: 'cluster', //开启cluster集群模式
instances: '0', //根据cpu可用核数运行最大数量的node应用实例
watch:true, //开启监听模式,任意文件内容发生改变,都会重启node应用
ignore_watch: [], //监听模式下,忽略的文件列表
env: { //默认的环境变量
NODE_ENV: "production",
MODE: "default"
},
env_production: { //生产环境变量,需要在命令行中添加参数 --env production
NODE_ENV: "production",
MODE: "pro"
},
env_pre_production: { //预生产环境变量,需要在命令行中添加参数 --env pre_production
NODE_ENV: "pre_production",
MODE: "pre"
}
},{
name: 'my-app2',
script: './src/index2.js',
exec_mode: 'fork', //默认的模式,只会在单核上运行node应用,无法充分利用多核cpu的性能,一般不推荐使用
env: {
NODE_ENV: "production",
MODE: "default"
},
env_production: {
NODE_ENV: "production",
MODE: "pro"
},
env_pre_production: {
NODE_ENV: "pre_production",
MODE: "pre"
}
}],
//部署相关的配置
deploy : {
//生产环境的部署,部署的方式以deploy的key作为区分
production : {
user : 'root', //服务器用户名
host : '8.8.8.8', //服务器ip地址
ref : 'origin/main', //需要拉取的仓库分支
repo : 'git@github.com:test/test.git', //仓库地址
path : '/var/test', //需要发布到服务器的路径
'pre-setup': '', //在安装进程启动之前需要执行的命令
'post-setup': "npm install && pm2 start ecosystem.config.js --env production", //拉取代码之后需要执行的指令
'pre-deploy': '', //部署之前的钩子,暂不清楚与'post-deploy'的区别,共同点是都可以进行reload的操作
'post-deploy': 'pm2 reload ecosystem.config.js --env production'
},
//预生产环境的部署,部署的方式以deploy的key作为区分
pre_production : {
user : 'root',
host : '8.8.8.8',
ref : 'origin/main',
repo : 'git@github.com:test/test.git',
path : '/var/test',
'pre-setup': '',
'post-setup': "npm install && pm2 start ecosystem.config.js --env pre_production",
'pre-deploy': '',
'post-deploy': 'pm2 reload ecosystem.config.js --env pre_production'
}
}
}
复制代码
使用pm2部署的完整指令是pm2 deploy <configuration_file> <environment> <command>
,默认的<configuration_file>就是ecosystem.config.js,所以可以省略该参数。就是deploy里面的key,可以区分不同的发布环境,指定需要执行的指令。
例如要发布到预生产环境上,执行的指令是pm2 deploy pre_production
。这里需要注意的是,如果是第一次发布,需要执行pm2 deploy pre_production setup
,从而走pre-setup和post-setup钩子,执行我们设置的初始化安装命令。还有一点需要注意的是由于存在拉仓库代码的行为,所以我们需要为服务器配置ssh免密登录,这样才能保证成功地拉下代码。
在发布完成后,我们可以登录到服务器上,输入pm2 list
,查看node应用的运行状态,如果是online,那么恭喜你,已经部署成功啦!
结语
ci/cd这一套流程其实会涉及很多知识,虽然在实践的过程中,会遇到很多问题,但是只有通过不断的实践,才能真正领悟其中的精髓。未来我还会尝试更多的ci/cd工具,同时也会把自己学到的经验整理成文分享出来,帮助需要的人。
个人博客
www.carlblog.site
最近自己搭建了个人博客,上面会定期发布关于技术经验总结的文章,希望感兴趣的小伙伴都去踩踩,不要跑堂啊!~