yaofly2012 / note

Personal blog
https://github.com/yaofly2012/note/issues
44 stars 5 forks source link

PM2 #131

Open yaofly2012 opened 4 years ago

yaofly2012 commented 4 years ago

PM2(Process Manager 2)

一、概述

是什么?

PM2 is a daemon process manager that will help you manage and keep your application online 24/7

看官网定义好像还是不知道pm2干嘛的。我们在通过node启动nodejs应用后,当关闭控制台应用程序也就被关闭了。但是通过pm2启动应用则不会这样,并且pm2可以让应用一直运行。

总结

实际是管理APP(即应用),让应用可以24/7运行,并且以多线程的方式启动应用。 这个通过pm2 monit命令可以看下Metadata:

image
  1. 每个应用都具有一个App Name
  2. 一个应用包含一个或多个进程Process;

Issues:

  1. online 24/7是什么鬼? 额,原来表示的是24小时*7天的意思,即007

干什么的?

  1. daemonize,monitor application;

  2. 不只是nodejs,还可以py,sh

  3. Process Management's action:

    • start 第一次执行具有添加的操作
    • stop
    • restart
    • 第一次执行具有添加的操作
    • 重启的时候可以修改环境变量
    • relaod 和restart啥区别?
    • delele 如果process正在运行,则会先stop。
  4. App属性

    • name
    • id
    • status
    • mode ?

Issues:

  1. 执行pm2 start app.js后为啥启动了三个控制台?
  2. 号称“Microservice”啥意思?

科普:

  1. process,thread
  2. PID

Process Management

分类

  1. app状态管理 start/stop/delete/restart/reload process
  2. 查看process
    • list/ls/l/status
    • 排序
    • show ids

参考:

  1. PM2
yaofly2012 commented 4 years ago

PM2 CLI

CLI options(即命令行入参)

  1. 内置的参数
  2. 自定参数 需要用--明确后面的是自定义参数
    # Pass extra arguments to the script
    -- arg1 arg2 arg3

    其中自定义参数可以通过process.argv访问(从第二个实参开始)

    process.argv[0] // node路径
    process.argv[1] // pm2的执行文件路径(pm2/lib/ProcessContainerFork.js)
    // 记下来就是自定义参数了
    process.argv[2] === arg1 
    process.argv[3] === arg2 
    process.argv[4] === arg3
yaofly2012 commented 4 years ago

Signals flow(信号流) & 优雅的关闭启动应用

一、关闭

1.1 什么时候关闭?

  1. 通过PM2 CLI主动关闭;
  2. 异常(应用启动失败,超时等);
  3. 用户主动关闭
    • 控制台窗口关闭按钮
    • Ctrl + C

1.2 关闭前需要做的事情?

  1. 资源清理工作
  2. More

    1.3 如何知道要被关闭了?

    监听信号

二、信号流

  1. 先发送SIGINT信号,告诉process要关闭了
    • 赶紧的做清理工作
    • 做完清理工作,自己关闭process.exit()
      
      process.on('SIGINT', function() {
      db.stop(function(err) {
      process.exit(err ? 1 : 0); // 清理完自己关闭进程
      });
      });

// kill process.on('SIGTERM', (err) => { db.stop(function(err) { process.exit(err ? 2 : 0); // 区分SIGINT }); });


2. 如果一段时间后,process没有关闭自己(即没有执行`process.exit()`),那PM2发送`SIGKILL`信号,告诉process,我要强制关闭你了。

### `SIGINT`(`SIGnal INTerrupt`的缩写)
PM2 `restart/reload/stop` process时触发
### `SIGKILL`(`SIGnal KILL`的缩写)

## 三、启动
1. process主动告诉PM2: `ready`
2. PM2可以等process ready(`--wait-ready`),但是process要在指定的时间内(`--listen-timeout`)一定ready

## 科普
1. 跨进程通讯 ?
2. `process.exit` & 实参意义?
错误码都是有特殊含义的[process_exit_codes](http://nodejs.cn/api/process.html#process_exit_codes)

3. CLI参数规范?
`--`, `-`, `name=vlaue`
yaofly2012 commented 4 years ago

日志管理

应用的日志输出管理(通过console模块记录的log):

  1. 展示
  2. 清理
  3. 重新加载

日志的meta

{
message: <string> // 应用中console.log打印的数据
timestamp: <string> // 日志记录的时间
type: <enum> // 日志类型: out, err, PM2
process_id: int // process id(PM2内部使用的进程ID)
app_name: <string> // 应用名称
}

日志输出

  1. 日志文件 看着实时的输出到日志文件里
  2. 控制台 可以实时的展示所有Process或则单独一个process的输出日志。

日志文件目录组织

--merge-logs\
--log-date-format="YYYY-MM-DD HH:mm:ss"\
--log /opt/logs/$appName/outerr.log\
--output /opt/logs/$appName/out.log\
--error /opt/logs/$appName/err.log

日志文件size限制

日志文件不能无限增长的,要不然磁盘空间全被日志文件占据了。

yaofly2012 commented 1 year ago

PM2 JS API

利用PM2 JS API可以在worker进程里调用pm2相关方法。相当于用编程的方式操作上层的PM2。

注意:

  1. PM2 JS API也是在worker线程里执行的。

pm2.launchBus((error, pm2_bus) => {})

可以收到所有进程利用process.send发送的消息。并且每个进程都会收到,可以实现消息广播。

const pm2 = require('pm2')

// 监听函数
pm2.launchBus(function(err, pm2_bus) {
/**
package结构:
{
  process: {
    namespace: 'default',
    rev: '781cefa74f9f6c9c7094c9ef41609a5e12c15b99',
    name: 'server',
    pm_id: 1
  },
  data: { success: true },
  at: 1669016559533
}
*/
  pm2_bus.on('process:msg', function(packet) {
    console.log(packet)
  })
})

// 触发消息
process.send({
  type : 'process:msg',
  data : {
    success : true
  }
})

pm2.sendDataToProcessId(packet)

向指定进程发消息,过程正好跟pm2.launchBus相反。

const pm2 = require('pm2');

// 触发消息
pm2.sendDataToProcessId({
  id: 124, // 可以从pm2.list接口里获取
  type: 'process:msg',
  top: true,
  data: { success: true }
})

// worker里监听消息
process.on('message', function(packet) {})