PM2管理node应用

215 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情

什么是PM2

pm2是基于nodejs开发的进程管理器,适用于后台常驻脚本管理,同时对node网络应用有自建负载均衡功能。按官方的说法,PM2 是一个守护进程管理工具,帮助您管理和守护您的应用程序。它以简单直观的 CLI 命令行方式进行工作。

总的来说,PM2有以下几个功能:

  1. 社区中使用最广泛的Node.js进程管理工具,支持进程负载均衡

  2. 当一个进程宕机,pm2会自动重启该服务,保证node.js应用的高可用性

  3. 提供一部分的APM能力,如进程监控

  4. 由于pm2也是由node.js写的,所以可以很方便的跟随应用去部署

PM2的使用

官方文档说的很清楚,跟着文档来问题就不大 pm2.keymetrics.io/docs/usage/…

安装PM2

npm install pm2 -g

启动一个应用

pm2 start app.js

参数的配置

# 给应用起一个别名
--name <app_name>

# 监听文件变化,当文件发生变化的时候会自动重新启动
--watch

# 指定日志文件
--log <log_path>

常见命令

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

# 停止某个应用进程
pm2 stop pid / all

# reload
pm2 reload xxx

# restart
pm2 restart xxx

restart和reload的区别:pm2.io/docs/runtim…

总结:restart会杀死再重启这个应用。reload实现0秒停机时间的重新加载,总是保证有一个进程在跑。如果reload没有成功的话,他会变成restart

pm2.json

我们还可以通过pm2.json文件来统一管理pm2的启动方式,以下是我在项目中使用的配置

{
  "apps": [{
    "name": "no-vnc-serve",
    "script": "index.js",
    "cwd": "./",
    "watch":"true",
    "error_file":"./logs/pm2.log",
    "out_file":"./logs/pm2.log",
    "log_date_format":"YYYY-MM-DD HH:mm Z",
    "instance_var": "INSTANCE_ID",
    "ignore_watch": [
      "node_modules",
      "logs"
    ]
  }]
}

实现PM2自启动

笔者想在windows系统中开机后自启动一个项目,根据官方文档,我们需要安装pm2-install

全局安装

npm install pm2 -g

安装windows自启动包

npm install pm2-windows-startup -g

执行命令

pm2-startup install

使用pm2启动项目

pm2 save

重启电脑可以查看

pm2 ls 查看

pm2启动流程

PM2首先会启动一个Client进程,之后会将启动业务进程所需要的配置,通过rpc传递给守护进程,由守护进程去启动进程。

PM2 start命令执行完成后业务进程会在后台开始运行,当后续想再针对业务进行一些操作时,就可以通过列表查看进程对应的pid,name来进行操作,同样是通过Client 触发rpc请求到守护进程,实现逻辑。 image.png

守护进程的概念 Daemon(守护进程) 是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或者等待处理某些发生的事件。它不需要用户输入就能运行而且提供某种服务。守护进程一般在系统启动时开始运行,除非强行终止,否则直到系统关机都保持运行。守护进程经常以超级用户(root)权限运行,因为它们要使用特殊的端口(1-1024)或访问某些特殊的资源。

pm2内置负载均衡

负载均衡是指将一组任务分配到一组资源上的过程,目的是使它们整体的处理更加高效。负载均衡可以优化响应时间,避免一些任务的计算节点不均匀过载而其他节点空闲

负载均衡主要有两种办法,静态算法和动态算法。静态算法,不需要考虑不同机器的状态;动态算法,通常更通用和更有效,但需要不同计算单元之间的信息交换(通信),会有影响性能的风险。

log4j日志管理

log4j配置文件

log4js.configure({
  appenders: { cheese: { type: "file", filename: "cheese.log" } },
  categories: { default: { appenders: ["cheese"], level: "error" } },
});

log4j的配置主要分成两个部分,分别是appenders和categories

appenders

appenders配置的是每一种的输出方式,你可以在appenders配置多种输出方式

out: {
    type: 'stdout',
},
dataFile: {
    type: 'dateFile',
    numBackups:7,//7天之前的文件即删除
    filename: '../logs/out.log',
    keepFileExt: true,
    maxLogSize: 20480000,
    backups: 4,
},

比如我这里配置了两种方式分别采用了stdout控制台输出和dataFile文件输出

categories

categories表示你选择你在appenders里面配置的那种输出方式输出

categories: {
    default:{
        appenders:['out','dataFile'],
        level:'debug', // 输出等级,只输出比这个等级高的
    },
},

这里我采用我在appenders里面配置的两种输出方式,即会输出到控制台和out.log这个文件中

实例化logger

// 当我在getLogger()里面不传任何参数的时候,默认对应categories里面default配置
// default配置再会根据我里面的appenders数组,去找appender中out和dataFile的配置
let logger = log4js.getLogger();

我们还可以实例出不同的logger,分别输出不同类型的文件

categories: {
    default: {
      appenders: ['consoleOut', 'default'],
      level: 'all',
    },
    error: {
      appenders: ['consoleOut', 'error'],
      level: 'warn',
    },
  },
 // 普通级别的logger,输出到控制台和日期分类的文件
const defaultLogger = log4js.getLogger('default')

 // 错误信息的logger,输出到控制台和error.log中
const errorLogger = log4js.getLogger('error')