nodeJS进程管理器pm2的使用


Posted in NodeJs onJanuary 09, 2019

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管理的所有进程信息,还会显示一个进程会被启动多少次,因为没处理的异常。

nodeJS进程管理器pm2的使用

pm2 monit

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

nodeJS进程管理器pm2的使用

入门教程

挑我们最爱的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

配置文件

  1. 配置文件里的设置项,跟命令行参数基本是一一对应的。
  2. 可以选择yaml或者json文件,就看个人洗好了。
  3. json格式的配置文件,pm2当作普通的js文件来处理,所以可以在里面添加注释或者编写代码,这对于动态调整配置很有好处。
  4. 如果启动的时候指定了配置文件,那么命令行参数会被忽略。(个别参数除外,比如--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, 发生异常的情况下自动重启;
}

自定义启动文件,创建一个test.json的示例文件,格式如下:

{
 "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 test.json

环境切换

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

对于这种场景,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

Web API

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

pm2 web

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

nodeJS进程管理器pm2的使用

pm2与forever对比

Feature Forever PM2
Keep Alive
Coffeescript  
Log aggregation  
API  
Terminal monitoring  
Clustering  
JSON configuration  

稳定运行建议

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

个人几点看法保证常驻应用进程稳定运行:

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

与supervisor对比

supervisor可以实现修改命令后重启应用,但是关闭控制台之后,整个进程就挂了。pm2则可以后台运行,关闭控制台之后也不影响进程运行。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

NodeJs 相关文章推荐
利用NodeJS的子进程(child_process)调用系统命令的方法分享
Jun 05 NodeJs
nodejs之请求路由概述
Jul 05 NodeJs
NodeJS和BootStrap分页效果的实现代码
Nov 07 NodeJs
Nodejs实现短信验证码功能
Feb 09 NodeJs
NodeJs下的测试框架Mocha的简单介绍
Feb 22 NodeJs
nodejs使用express创建一个简单web应用
Mar 31 NodeJs
docker中编译nodejs并使用nginx启动
Jun 23 NodeJs
nodejs密码加密中生成随机数的实例代码
Jul 17 NodeJs
深入解析nodejs HTTP服务
Jul 25 NodeJs
nodejs中用npm初始化来创建package.json的实例讲解
Oct 10 NodeJs
深入理解NodeJS 多进程和集群
Oct 17 NodeJs
浅谈JS和Nodejs中的事件驱动
May 05 NodeJs
NodeJS模块与ES6模块系统语法及注意点详解
Jan 04 #NodeJs
nodejs 使用http进行post或get请求的实例(携带cookie)
Jan 03 #NodeJs
详解nodejs 配置文件处理方案
Jan 02 #NodeJs
nodejs基础之多进程实例详解
Dec 27 #NodeJs
nodejs基础之常用工具模块util用法分析
Dec 26 #NodeJs
nodejs基础之buffer缓冲区用法分析
Dec 26 #NodeJs
nodejs异步编程基础之回调函数用法分析
Dec 26 #NodeJs
You might like
PHP+MySQL投票系统的设计和实现分享
2012/09/23 PHP
PHP构造函数与析构函数用法示例
2016/09/28 PHP
php删除txt文件指定行及按行读取txt文档数据的方法
2017/01/30 PHP
thinkPHP3.2.3实现阿里大于短信验证的方法
2018/06/06 PHP
浅谈Javascript Base64 加密解密
2014/12/28 Javascript
javascript判断移动端访问设备并解析对应CSS的方法
2015/02/05 Javascript
详解JavaScript数组的操作大全
2015/10/19 Javascript
Javascript之Math对象详解
2016/06/07 Javascript
Bootstrap 最常用的JS插件系列总结(图片轮播、标签切换等)
2016/07/14 Javascript
jquery实现全选、不选、反选的两种方法
2016/09/06 Javascript
vue拦截器实现统一token,并兼容IE9验证功能
2018/04/26 Javascript
Vue中props的使用详解
2018/06/15 Javascript
vue动态删除从数据库倒入列表的某一条方法
2018/09/29 Javascript
Angular(5.2-&gt;6.1)升级小结
2018/12/27 Javascript
Vue调用后端java接口的实例代码
2019/10/28 Javascript
JavaScript对象原型链原理详解
2020/02/05 Javascript
ssm+vue前后端分离框架整合实现(附源码)
2020/07/08 Javascript
vue实现点击出现操作弹出框的示例
2020/11/05 Javascript
vue data有值,但是页面{{}} 取不到值的解决
2020/11/09 Javascript
[47:12]TFT vs Secret Supermajor小组赛C组 BO3 第三场 6.3
2018/06/04 DOTA
使用Python从有道词典网页获取单词翻译
2016/07/03 Python
python通过zabbix api获取主机
2018/09/17 Python
Python实现获取汉字偏旁部首的方法示例【测试可用】
2018/12/18 Python
Python爬虫库BeautifulSoup的介绍与简单使用实例
2020/01/25 Python
CSS3中animation实现流光按钮效果
2020/12/21 HTML / CSS
HTML5页面音视频在微信和app下自动播放的实现方法
2016/10/20 HTML / CSS
英国健身超市:Fitness Superstore
2019/06/17 全球购物
介绍一下linux的文件权限
2014/07/20 面试题
畜牧兽医本科生个人的自我评价
2013/10/11 职场文书
求职简历中的自我评价分享
2013/12/08 职场文书
文科毕业生自荐书范文
2014/04/17 职场文书
红领巾心向党演讲稿
2014/09/10 职场文书
民主评议党员自我评议范文2014
2014/09/26 职场文书
2016简历自荐信优秀范文
2016/01/29 职场文书
总结python多进程multiprocessing的相关知识
2021/06/29 Python
python神经网络 tf.name_scope 和 tf.variable_scope 的区别
2022/05/04 Python