前端SPA+后端Node分离项目的线上部署之——PM2进程管理工具

1,034 阅读8分钟

1.安装pm2

使用包管理工具全局安装PM2npm install pm2 -g,因为这个pm2是所有node项目通用的进程管理工具,全局安装为了所有的项目都可以用pm2来进行进程管理

2.了解常用命令

  • pm2 start bin/www启动进程
  • pm2 start app.js --name abc 启动进程

并且使用别名,方便后续命令可以通过别名访问

  • pm2 start bin/www添加进程

可以同时存在多个不同的项目进程

  • pm2 stop www结束进程

也可以通过别名

  • pm2 stop all结束所有进程

stop用于暂停,重新开启的时候原先的restart记录还会存在,并且按照原先配置启动,更新的配置不会生效,delete用于彻底关闭进程,delete关闭后再开启会启用最新的配置

  • pm2 delete www删除进程

  • pm2 delete all删除所有进程

  • pm2 list 列出所有进程

  • pm2 describe www查看某个进程具体情况

  • pm2 monit查看进程的资源消耗情况(监控资源)

  • pm2 logs 序号/名称查看pm2的日志

是pm2的日志,不是项目具体的日志,项目具体的日志会单独打印在自己设置的路径文件中

  • pm2 logs www若要查看具体某个进程的日志记得添加别名

  • pm2 restart www重新启动进程

会更新配置文件,相当于delete+start

  • pm2 restart all重新启动所有进程

restart在多个进程下会全部重新启动所有进程,reload在多个进程下会轮流启动所有进程,等待前一个进程重启完毕才重启第二个进程,保证至少有1个进程正在工作,实现0秒宕机重启所有进程

  • pm2 reload www0秒宕机重启所有进程

3.配置一个json配置文件代替繁琐命令后缀

我们在通过命令启动项目时如果需要配置一些参数就需要通过-xxx后缀的方式很繁琐,例如--watch,--instances,--ignore-watch,--name,--output, --error不仅每次都需要重新加上参数,还不便于维护 所以我们在项目根目录新建一个pm2.conf.json文件

这是我的配置文件

{
  "apps": {
    "name": "weibo", //代替--name,为项目创建别名
    "script": "dist/bin/www.js",//启动的文件
    "watch": ["dist"],//一个数组代表要监听的文件夹或文件,也可以使用布尔值代表全部监听或者全不监听
    "ignore_watch": [  "node_modules", "logs" ],// 不用监听的文件
    "watch_options": {
      "usePolling": true //有时候监听会失效,那么加上这个watch配置项
    },
    "max_restarts": 10,//1s内重启了多少次就不再重启了,防止出现异常错误时无限重启浪费资源
    "instances": 4,//应用启动实例个数,仅在cluster模式有效
    "exec_mode": "cluster",//集群的模式可以实cluster和fork
    "error_file": "logs/err/err.log",//错误日志打印位置
    "out_file": "logs//res/res.log",//一般日志打印位置
    "merge_logs": true,//是否追加日志而不是每次都新建日志,一般与PM2-logrotate一起使用
    "log_data_format": "YYYY-MM-DD HH:mm:ss"//pm2日志的时间格式化
  }
}

具体还有许许多多的配置可以到PM2官网查看

3.与日志管理工具pm2-logrotate一起使用

在线上环境的时候控制台打印的东西我们不能像开发环境一样一眼就可以看到,如果配置了 "error_file" "out_file"此时pm2会将console.err全部转发到error_file的文件中,会将console.log全部转发到out_file的文件中如果没有则新建,如果开启了多个进程,默认会有多个文件生成代表不同进程的日志例如err-0.log,err-1.log等等,如果不加限制,并且随着时间的推移,日志会越来越难管理,所以PM2存在一个日志管理工具pm2-logrotate来管理配置

安装pm2-logrotate

使用pm2 install pm2-logrotate,使用前必须要在PM2的配置文件下追加 "merge_logs": true

配置pm2-logrotate(使用pm2 conf pm2-logratate查看当前配置项)

  • max_size(默认为10M):当文件大小大于此值时,它将重新新建一个名如err-log__2022-01-11_11-01-01.log的文件(自己配置的文件名+时间),可以在末尾指定单位:10M 10G 10M 10K,但是第一次生成的文件在没超过大小前还是不会携带时间而是你原本设置的名字,等到第一个日志超出大小才会生成带有时间的文件
  • retain(默认为30):此数字是一次保留的轮换日志数,表示最多有多少个同类型日志文件存在,比如设置30后等到日志文件累积到30个之后再新建日志则会删除最早的那个文件,使其动态平衡至30个文件
  • compress(默认值为false):通过 gzip 为所有轮换的日志启用压缩
  • dateFormat(默认为 YYYY-MM-DD_HH-mm-ss):数据的格式使用日志文件的名称
  • rotateModule(默认为 true):是否启动pm2模块的日志分割功能
  • workerInterval(默认为30秒):您可以控制工作线程检查日志大小的时间间隔(最小值为1)
  • rotateInterval(默认为每天午夜):此 cron 用于在执行时强制分割,例如到了24:00无论你的日志有没有超过你设置的max_size都会重新生成一个新的日志文件
  • TZ(默认为系统时间):这是用于偏移保存的日志文件的标准 

修改配置

采用pm2 set pm2-logrotate:<param> <value>的格式,例如 $ pm2 set pm2-logrotate:TZ Asia/Shanghai 设置TZ为上海时区的标准

4.与log4js一起使用

如果只有一个进程任务,则于log4js使用不会出错,但是如果开启了集群模式"exec_mode": cluster并且instances超过1个进程,此时log4js会与pm2起冲突导致log4js的日志系统无法正常打印

解决方式

1.在log4js配置中追加disableClustering: true,缺点:会丢失日志(不建议使用)

log4js.configure({
     disableClustering: true,//关键
    appenders: {
        out: { type: 'console', layout:{type:'pattern',pattern:'%[[%d] [%p]%] - %m'} },
        allLog: { type: 'dateFile', filename: './logs/app.log', layout:{type:'pattern',pattern:'[%d] [%p] - %m'} }

    },
    categories: {
        default: { appenders: ['out', 'allLog'], level: 'debug'},
    }

});

2.在log4js配置中追加 pm2: true, pm2InstanceVar: 'INSTANCE_ID',但是要先安装pm2-intercom进程间通信模块

log4js.configure({
     pm2: true,
     pm2InstanceVar: 'INSTANCE_ID',
    appenders: {
        out: { type: 'console', layout:{type:'pattern',pattern:'%[[%d] [%p]%] - %m'} },
        allLog: { type: 'dateFile', filename: './logs/app.log', layout:{type:'pattern',pattern:'[%d] [%p] - %m'} }

    },
    categories: {
        default: { appenders: ['out', 'allLog'], level: 'debug'},
    }

});

3.放弃使用log4js,使用PM2+pm2-logrotate自己的日志功能,我个人感觉pm2自带的日志功能很够用了,而且如果采用log4js的日志系统需要调用它的api来打印,pm2的话直接采用最原始的console使得你在开发环境(没用pm2的时候可以打印在控制台),开启pm2后自动输出到日志文件中十分实用,不过相比log4js还是有不足之处,比如console不能携带时间戳(但是自己可以封装实现),pm2只支持err和out两种格式,log4js可以支持不同的参数打印到不同的文件中等

5.exec_mode的fork和cluster的区别

fork模式,单实例多进程,常用于多语言混编,比如php、python等,各自占用一个端口,需要自己做应用的端口分配和负载均衡的子进程业务代码 缺点:单服务器实例容易由于异常会导致所有服务崩溃。

cluster模式,多实例多进程,但是只支持node(基于node的cluster模块),端口可以复用(所有实例只占用一个端口),不需要额外的端口配置,不需要自己写额外代码来配置 优点就是由于多实例机制,可以保证服务器的容错性,就算一个进程出现异常也不会使多个服务器实例同时崩溃。

线上环境的部署

1.把原来的ts文件用tsc命令编译成js的dist文件,把你的dist上传到服务器(node_modules不要上传),pm2.conf.json和package.json不要忘了上传 2.利用宝塔软件商店下载pm2管理器或者node管理器 3.打开宝塔面板->网站->node项目->添加项目

image.png 4.点击启动的时候会自动执行你选中的script命令(这里是启动pm2)

注意事项(我都踩过)

1.windows和linux系统文件分隔符号不同windows:'\\',linux:'/'
解决方法:可以用node的os.type模块判断当前是什么系统返回不同分隔符
2.linux中mysql会区分大小写,windows不会,如果开始没做处理会造成找不到表名等错误 解决方法:给mysql配置文件加上lower_case_table_names=1忽略大小写

image.png 3.项目默认是用www用户切换的,所以在终端pm2 list默认是root用户所以找不到你已经启动的项目需要切换到www用户再用pm2 list查看
解决方式:su www切换到www用户 ,如果提示not available导致切换不了可以尝试 usermod -s /bin/bash www后再次切换,使用whoami可以查看当前是哪个用户