PM2入门

197 阅读5分钟

简介

最近在回顾NodeJS的知识体系,这篇用于总结如何使用PM2去启动Node服务以及其的基本用法。

PM2是一个守护进程管理器,它将帮助您管理和保持应用程序在线。带有内置负载均衡器。它有助于促进生产部署,并使您能够无限期地保持正在运行的应用程序(即使发生事故时)。它还可以让您深入了解应用程序的运行时性能资源消耗,并通过其集群功能实时扩展应用程序

守护进程

在开始PM2用法配置之前先来了解一下什么是守护进程
守护进程就是运行在后台不受中断的影响。开发NodeJS程序时,当我们打开终端执行node app.js开启一个服务进程后,该终端会一直处于占用状态。终止终端即结束NodeJS服务。如果才有守护进程的方式,在当前终端执行node app.js依旧可以执行其他操作。且不会影响NodeJS服务的运行。(通过NodeJS的spawn即可创建守护进程)
PS: 之前面试也遇到问我探针是什么? 大致意思就是用于检测程序是否正常运行的一种手段

PM2基础使用

启动应用程序(也可以.sh或者其他文件)
pm2 start XXX.js

重启应用程序服务(硬重启例如开机、关机的重启)
pm2 restart <id/name>

因为我们一般是多进程,reload一般保证是可用性的重启,
也就是说他会一个进程一个进程的重启,总是保证有进程是可以被可用的,这就是比较友好的
pm2 reload 

列出管理的所有应用程序的状态
pm2 list 

查看id/name的日志
pm2 logs <id/name>

终止id/name
pm2 stop <id/name>

删除id/name
pm2 stop <id/name>

性能监控 (占用CPU多少)
pm2 monit

如上是基础命令的使用。这篇文章详细介绍了

PM2 配置文件

创建配置文件同时管理多个应用。 接下来编写一个配置文件,来启动本地的Koa项目.

  • 通过命令初始化ecosystem.config.js文件
生成ecosystem.config.js配置文件。如果想创建自己的配置文件以.config.js结尾,PM2能够识别为配置文件
pm2 init simple
  • 编写ecosystem.config.js启动两个NodeJS服务
// pm2 app 配置信息
const os = require('os');
const cpuCoreLength = os.cpus().length; 
module.exports = {
  apps : [{
    name: 'AKclown', // 当前服务名称
    script: './app.js', // 当前执行的脚本
    // watch:true,   // 监听重启,启用情况下,文件夹或子文件夹下变化应用自动重启
    ignore_watch: ['node_module', '__test__', 'logs'], // 忽略监听的文件夹,支持正则表达式
    instances: 1, // 应用启动实例个数,仅在cluster模式有效,默认为fork (线上多线程 | 本地单线程就可以了)
    error_file: './logs/err.log', // 记录标准错误流
    out_file: './logs/out.log',  //  记录标准输出流
    log_date_format: 'YYYY-MM-DD HH:mm:ss Z', // Z 表示使用当前时区的时间格式
    combine_logs: true, // 多个instances实例时进行日志合并 
    max_memory_restart: '300M', // 内存泄漏时重启 (设置该值的依据是:通过pm2 monit查看多少,然后在这个基数上乘以2或者3即可)
  },
  {
   name: 'AKclown1',
   script: './index.js',
   ...
  }]
}

如下是启动本地AKclownAKclown1两个服务。可以通过pm2 list来进行查看 image.png

  • 执行配置文件命令pm2 [start | restart | stop | reload |delete] ecosystem.config.js
  • 有时候ecosystem.config.js配置了多个服务,但我只想针对其中一个服务进行操作,在执行命令中添加--only指定服务名称即可
pm2 start ecosystem.config.js --only 服务名称

image.png

  • 配置环境变量
    我们可以通过env.*来指定不同的环境变量。在执行配置文件追加--env [*]即可注入对应的环境变量。因此我们在业务代码中可以通过process.env.~来获取当前环境的值,从而做逻辑区分处理
ecosystem.config.js
module.exports = {
  apps : [{
    ...
    env_production: {
       NODE_ENV: "production"
    },
    env_development: {
       NODE_ENV: "development"
    }
  },
}

执行命令

pm2 start ecosystem.config.js --env production

image.png image.png

以上就是基本的配置。关于配置文件更多的参数支持请查看该文档

PM2日志拆分

为什么需要日志拆分呢? 如下是我用了几秒就累计了的请求日记。这还只是我在本地测试的以及是最简单的demo。如果线上用户量很大以及系统完整,可以想象的到日志记录文件得多大。如果一个日志文件有几个G,那么我们也会很难打开它,以及系统出现问题时也不好排查。因此我们需要对日志进行拆分。一般情况下以为单位即可 image.png

  • 使用pm2-logrotate来进行日志拆分
pm2 install pm2-logrotate -g
  • 通过pm2 list查看pm2-logrotate进程 image.png
  • pm2-logrotate的默认配置如下
pm2 set pm2-logrotate:max_size 10M # 日志文件最大为10M
pm2 set pm2-logrotate:retain 30 # 保留30个文件,多了就自动删除
pm2 set pm2-logrotate:compress false # gzip压缩文件
pm2 set pm2-logrotate:dateFormat YYYY-MM-DD_HH-mm-ss # 日期格式
pm2 set pm2-logrotate:workerInterval 30 # 单位 s ,日志检查的时间间隔
pm2 set pm2-logrotate:rotateInterval 0 0 ***# 定时规则
pm2 set pm2-logrotate:rotateModule true # 分割 pm2 模块的日志

修改配置 pm2 set pm2-logrotate:<key> <value>

这需要补充说明一下rotateIntervalrotateModule

  1. rotateInterval 0 0 * * * 是什么意思呢? 0 0 表示每天的0点0分去拆分日志。规则如下图,其名称为crontab定时规则

image.png
2. rotateModule 指的是,pm2-logrotate是一个模块的服务,它也有日志也需要拆分。其他模块的日志也需要拆分一下

总结

通过该文章我们知道了什么是守护进程|pm2的基础用法|pm2配置文件的编写|pm2如何进行日志拆分。想学习更多请solo官网

参考资料

A Complete Guide to Node.js Process Management with PM2