pm2是一个带有负载均衡功能的Node应用的进程管理器。当你要把你的独立代码利用全部的服务器上的所有CPU,并保证进程永远都活着,0秒的重载, PM2是完美的。

pm2是开源的基于Nodejs的进程管理器,包括守护进程,监控,日志的一整套完整的功能,基本是Nodejs应用程序不二的守护进程选择,事实上它并不仅仅可以启动Nodejs的程序,只要是一般的脚本的程序它同样可以胜任。

~、 主要特性:

内建负载均衡(使用Node cluster 集群模块)
后台运行
0秒停机重载(这项功能允许你重新载入代码而不用失去请求连接。)
具有Ubuntu和CentOS 的启动脚本
停止不稳定的进程(避免无限循环)
控制台检测
提供 HTTP API
远程控制和实时的接口API ( Nodejs 模块,允许和PM2进程管理器交互 )

~、 使用环境:

仅能用于web应用
运行于Node 0.11.x版本
运行于 cluster 模式(默认模式)

~、 安装

npm install -g pm2

pm2安装好后,会自动创建下面目录:

/.pm2  
/.pm2/logs   
/.pm2/pids  
/.pm2/pm2.log 
/.pm2/pm2.pid 
/.pm2/rpc.sock 
/.pm2/pub.sock 
/.pm2/conf.js 

~、用法

npm install pm2 -g                   # 命令行安装 pm2 
pm2 start app.js -i 4                #后台运行pm2,启动4个app.js 
                                               # 也可以把'max' 参数传递给 start
                                               # 正确的进程数目依赖于Cpu的核心数目
pm2 start app.js --name my-api # 命名进程
pm2 list                                 # 显示所有进程状态
pm2 monit                                # 监视所有进程
pm2 logs                                 #  显示所有进程日志
pm2 stop all                             # 停止所有进程
pm2 restart all                          # 重启所有进程
pm2 reload all                           # 0秒停机重载进程 (用于 NETWORKED 进程)
pm2 stop 0                               # 停止指定的进程
pm2 restart 0                            # 重启指定的进程
pm2 startup                              # 产生 init 脚本 保持进程活着
pm2 web                                  # 运行健壮的 computer API endpoint (http://localhost:9615)
pm2 delete 0                             # 杀死指定的进程
pm2 delete all                           # 杀死全部进程

运行进程的不同方式:

$ pm2 start app.js -i max  # 根据有效CPU数目启动最大进程数目
$ pm2 start app.js -i 3      # 启动3个进程
$ pm2 start app.js -x        #用fork模式启动 app.js 而不是使用 cluster
$ pm2 start app.js -x -- -a 23   # 用fork模式启动 app.js 并且传递参数 (-a 23)
$ pm2 start app.js --name serverone  # 启动一个进程并把它命名为 serverone
$ pm2 stop serverone       # 停止 serverone 进程
$ pm2 start app.json        # 启动进程, 在 app.json里设置选项
$ pm2 start app.js -i max -- -a 23                   #在--之后给 app.js 传递参数
$ pm2 start app.js -i max -e err.log -o out.log  # 启动 并 生成一个配置文件
你也可以执行用其他语言编写的app  ( fork 模式):
$ pm2 start my-bash-script.sh    -x --interpreter bash
$ pm2 start my-python-script.py -x --interpreter python

pm2 list
列出由pm2管理的所有进程信息,还会显示一个进程会被启动多少次,因为没处理的异常。

pm2 monit
监视每个node进程的CPU和内存的使用情况。

~、入门教程

挑我们最爱的express应用来举例。一般我们都是通过npm start启动应用,其实就是调用node ./bin/www。那么,换成pm2就是

pm2 start ./bin/www –watch

这里用了–watch参数,意味着当你的express应用代码发生变化时,pm2会帮你重启服务。

~、参数说明:

--watch:监听应用目录的变化,一旦发生变化,自动重启。如果要精确监听、不见听的目录,最好通过配置文件。
-i --instances:启用多少个实例,可用于负载均衡。如果-i 0或者-i max,则根据当前机器核数确定实例数目。
--ignore-watch:排除监听的目录/文件,可以是特定的文件名,也可以是正则。比如--ignore-watch="test node_modules "some scripts""
-n --name:应用的名称。查看应用信息的时候可以用到。
-o --output <path>:标准输出日志文件的路径。
-e --error <path>:错误输出日志文件的路径。
--interpreter <interpreter>:the interpreter pm2 should use for executing app (bash, python...)。比如你用的coffee script来编写应用。

完整命令行参数列表:

pm2 start app.js –watch -i 2  

**配置文件 **

配置文件里的设置项,跟命令行参数基本是一一对应的。

可以选择js或者json文件,就看个人洗好了。

json格式的配置文件,pm2当作普通的js文件来处理,所以可以在里面添加注释或者编写代码,这对于动态调整配置很有好处。

如果启动的时候指定了配置文件,那么命令行参数会被忽略。(个别参数除外,比如--env)
举个简单例子:

{ 
    "name" : "fis-receiver",                // 应用名称 
    "script" : "./bin/www",                 // 实际启动脚本 
    "cwd" : "./",                           // 当前工作路径 
    "watch": [                              // 监控变化的目录,一旦变化,自动重启 
        "bin", "routers" 
    ], 
    "ignore_watch" : [                      // 从监控目录中排除 
        "node_modules", "logs", "public"
    ], 
    "watch_options": { 
        "followSymlinks": false 
    }, 
    "error_file" : "./logs/app-err.log",    // 错误日志路径 
    "out_file" : "./logs/app-out.log",      // 普通日志路径 
    "env": { 
        "NODE_ENV": "production"            // 环境变量,object类型,如{"NODE_ENV":"production", "ID": "42"};
    },
    "instances" : "max",                    // 开启进程数,可为数值,也可为max。与服务器cpu核数相关。应用启动实例个数,仅在cluster模式有效,默认为fork;
    "exec_mode" : "cluster"                 // 应用启动模式,支持fork和cluster模式;cluster(多核推荐)
    "min_uptime": "60s",                    // 应用运行少于时间被认为是异常启动;
    "max_restarts": 30,                     // 最大异常重启次数,即小于min_uptime运行时间重启次数;
    "max_memory_restart": "300M",           // 最大内存限制数,超出自动重启;
    "autorestart": true,                    // 默认为true, 发生异常的情况下自动重启;
}

pm2启动文件,

pm2 init

创建一个ecosystem.config.js的示例文件,格式如下:

module.exports =  {
  "apps":[
    {
      "name": "test",
      "cwd": "/data/wwwroot/nodejs",
      "script": "./test.sh",
      "exec_interpreter": "bash",
      "min_uptime": "60s",
      "max_restarts": 30,
      "exec_mode" : "cluster_mode",
      "error_file" : "./test-err.log",
      "out_file": "./test-out.log",
      "pid_file": "./test.pid"
      "watch": false
    }
]}

~、参数说明:

apps:json结构,apps是一个数组,每一个数组成员就是对应一个pm2中运行的应用
name:应用程序的名称
cwd:应用程序所在的目录
script:应用程序的脚本路径
exec_interpreter:应用程序的脚本类型,这里使用的shell,默认是nodejs
min_uptime:最小运行时间,这里设置的是60s即如果应用程序在60s内退出,pm2会认为程序异常退出,此时触发重启max_restarts设置数量
autorestart 默认为true, 发生异常的情况下自动重启;
max_restarts:设置应用程序异常退出重启的次数,默认15次(从0开始计数)
exec_mode:应用程序启动模式,这里设置的是cluster(集群),默认是fork
error_file:自定义应用程序的错误日志文件
out_file:自定义应用程序日志文件
pid_file:自定义应用程序的pid文件
watch:是否启用监控模式,默认是false。如果设置成true,当应用程序变动时,pm2会自动重载。这里也可以设置你要监控的文件。
max_memory_restart:当内存超过设置的数量时自动重启。 如果工程中有比较棘手的内存泄露问题,这个算是一个折中方案。
instances: 启用多少个实例,可用于负载均衡。仅在cluster模式有效,默认为fork;
cron_restart crontab时间格式,定时重启应用,目前只支持cluster模式;
运行实例:已上面的test.json为例

pm2 start ecosystem.config.js

~、环境切换

在实际项目开发中,我们的应用经常需要在多个环境下部署,比如开发环境、测试环境、生产环境等。在不同环境下,有时候配置项会有差异,比如链接的数据库地址不同等。

对于这种场景,pm2也是可以很好支持的。首先通过在配置文件中通过env_xx来声明不同环境的配置,然后在启动应用时,通过–env参数指定运行的环境。

首先,在配置文件中,通过env选项声明多个环境配置。简单说明下:

env为默认的环境配置(生产环境),env_dev、env_test则分别是开发、测试环境。可以看到,不同环境下的NODE_ENV、REMOTE_ADDR字段的值是不同的。
在应用中,可以通过process.env.REMOTE_ADDR等来读取配置中生命的变量。

例如:

"env": { "NODE_ENV": "production","REMOTE_ADDR": "http://www.example.com/"}
"env_dev": { "NODE_ENV": "development", "REMOTE_ADDR": "http://wdev.example.com/"} 
​"env_test": { "NODE_ENV": "test", "REMOTE_ADDR": "http://wtest.example.com/"}

启动指明环境:假设通过下面启动脚本(开发环境),那么,此时process.env.REMOTE_ADDR的值就是相应的链接地址

pm2 start app.js --env dev

~、负载均衡

命令如下,表示开启三个进程。如果-i 0,则会根据机器当前核数自动开启尽可能多的进程。

m2 start app.js -i 3 # 开启三个进程  
​pm2 start app.js -i max # 根据机器CPU核数,开启对应数目的进程 

日志查看

除了可以打开日志文件查看日志外,还可以通过pm2 logs来查看实时日志。这点对于线上问题排查非常重要。

比如某个node服务突然异常重启了,那么可以通过pm2提供的日志工具来查看实时日志,看是不是脚本出错之类导致的异常重启。

pm2 logs  

~、开机自动启动

可以通过pm2 startup来实现开机自启动。大致流程如下:

通过pm2 save保存当前进程状态。

通过pm2 startup [platform]生成开机自启动的命令。(记得查看控制台输出)

将步骤2生成的命令,粘贴到控制台进行,搞定。

自动重启应用

fork不支持定时重启,cluster支持定时重启。定时重启也就是配置中的cron_restart配置项。

~、监控(monitor)

运行如下命令,查看当前通过pm2运行的进程的状态。

pm2 monit

内存使用超过上限自动重启

如果想要你的应用,在超过使用内存上限后自动重启,那么可以加上–max-memory-restart参数。(有对应的配置项)

pm2 start big-array.js –max-memory-restart 20M     

如果你不仅仅想监控被pm2管理的进程,还需要监控进程所运行的机器的信息,你可以使用下面这个API。

pm2 web  

pm2会启动一个叫做pm2-http-interface的进程提供web服务。你打开浏览器输入 http://127.0.0.1:9615,是不是被看到的结果惊艳到了。

~、稳定运行建议

PM2是一款非常优秀的Node进程管理工具,它有着丰富的特性:能够充分利用多核CPU且能够负载均衡、能够帮助应用在崩溃后、指定时间(cluster model)和超出最大内存限制等情况下实现自动重启。

个人几点看法保证常驻应用进程稳定运行:
定时重启,应用进程运行时间久了或许总会产生一些意料之外的问题,定时可以规避一些不可测的情况;
最大内存限制,根据观察设定合理内存限制,保证应用异常运行;
合理min_uptime,min_uptime是应用正常启动的最小持续运行时长,超出此时间则被判定为异常启动;
设定异常重启延时restart_delay,对于异常情况导致应用停止,设定异常重启延迟可防止应用在不可测情况下不断重启的导致重启次数过多等问题;
设置异常重启次数,如果应用不断异常重启,并超过一定的限制次数,说明此时的环境长时间处于不可控状态,服务器异常。此时便可停止尝试,发出错误警告通知等。