前言

Node服务在本地环境运行可用nodemon实现热启动,那照搬这套模式到服务器中让Node服务运行起来可行吗?看上去可行,实际还会存在一些在本地环境也能模拟出来的问题。
把本地环境当作服务器,正常来说会存在关机的可能,关机意味着要关闭CMD工具,这样做会把Node进程杀掉。在服务器中是不允许出现这种情况的,期望是即使退出CMD工具,Node进程也会保留下来,继续在服务器后台中运行。
基于上述情况,在服务器中部署Node服务一般都会使用相关工具监控其运行状态,因某些原因导致报错、崩溃或关闭,需在适合时机重启该服务。监控Node服务的运行状态可用以下工具解决。

虽然上述提到的三种Node进程管理工具可在不同场景被应用,但在选择工具解决问题前充分认识三者间的差别是很有必要的。

工具 稳定性 运行环境 并发量级 后台运行 代码监听 状态监控 日志管理 集群模式
nodemon 中等 开发环境 ✔️
forever 中等 生产环境 较小 ✔️ ✔️ ✔️
pm2 较高 生产环境 较大 ✔️ ✔️ ✔️ ✔️ ✔️

从三者区别可知,nodemon适用于开发环境,调试代码更方便;forever适用于无需监控且访问量较小的Node服务,pm2适用于需监控且访问量较大的Node服务。很多时候为了更方便通过日志或状态得知当前Node进程的相关信息,选择pm2可能更为稳定。本章将带领你让Node服务永驻在后台中,基于pm2部署Node服务,使其不受外力影响的情况下永驻服务器的后台中,即使受到外力影响也能及时重启,保障Node服务的可靠性与稳定性。

背景:Pm2是什么

pm2是一个运行在Node环境的守护进程管理器,用于管理Node进程。
它作为一个轻量级工具,麻雀虽小但功能强大,以下特性都是其他同类型工具无法媲美的。

后台运行

执行node src/index.js启动的Node进程,会随着CMD工具的关闭而结束。pm2启动的Node进程,不会随着CMD工具的关闭而结束。

代码监听

监听代码文件,若发生改动会重启Node进程。

次数限制

限制不稳定的重启次数,达到上限就结束Node进程。

零秒重启

在集群模式中,可做到重启时不会结束Node进程。

负载均衡

在集群模式中,自动使用轮询方式达到负载均衡,减轻服务器压力。

实时接口

提供Node进程监控状态的实时接口,返回服务器与Node进程的相关信息。pm2-web是一个可视化Node进程监控体统,其使用了这些实时接口方便地展示当前的监控数据。不过该项目已多年未维护,因此也只能参考其源码自行开发一个监控系统了。

日志管理

收集的日志文件可配合插件管理与细化。

集成管理

对于多个Node进程,在不同环境中可通过同一个配置文件统一管理。

方案:让Node服务永驻在后台中

打开CMD工具,登录服务器。执行npm i -g pm2安装pm2,再执行pm2 -v,输出版本表示安装成功。
其最基本的启动命令是pm2 start,可用命令或配置文件维护Node进程。以下围绕命令的形式熟悉pm2如何管理Node进程。
以第12章开发的小型接口系统为例。执行npm start,输出以下信息。想通过CMD工具执行其他命令是不可能的,必须将终端的进程关闭或创建新的终端再执行其他命令。

若使用pm2执行npm start,就不会出现该问题了。执行pm2 start src/index.js,启动进程后输出一些关键信息就会将进程隐藏到后台,终端的操作权限继续交由用户。既不会占用终端的操作权限,也能让Node进程在后台运行。

字段

输出信息是一个包括多个字段的表格,id与name是一个Node进程的标识,在执行停止命令或删除命令可指定某个Node进程。

字段 功能 参数 描述
id 服务ID ~ 自动以递增方式生成
name 服务名称 ~ 通过–name设置
mode 进程模式 fork/cluster 单个进程或多个进程
重启次数 ~ 自动记录
status 进程在线 online/stopped 在线或停止
cpu cpu占用率 ~ 自动记录
memory 内存占用大小 ~ 自动记录
命令

pm2命令超多,但很多命令对开发者来说用不上,只需掌握以下命令就能操作pm2。

命令 功能
`pm2 restart <name id all>` 重启进程
`pm2 reload <name id all>` 重载进程
`pm2 stop <name id all>` 停止进程
`pm2 delete <name id all>` 杀死进程
`pm2 show <name id>` 查看进程信息
pm2 ls 查看进程列表
pm2 monit 查看面板信息
pm2 logs 查看进程日志信息
指标

执行pm2 start src/index.js只会输出一个包括少量关键信息的表格,若想查看更多进程信息,可执行pm2 show <name|id>输出更多进程信息。以下截图有些信息较重要,需简单了解。

restarts表示重启次数,uptime表示运行时间,script path表示启动入口文件,script args表示启动入口文件的附带参数,error log path表示错误日志路径,out log path表示输出日志路径,exec mode表示进程模式,watch & reload表示是否开启监听文件变动重启,unstable restarts表示不稳定的重启次数。

used heap size表示堆内存使用情况,heap usage表示堆内存使用率,heap size表示堆内存,event loop latency表示事件循环时延。
为了装逼,还可执行pm2 monit查看面板信息。左上角是进程列表,右上角是全部实时日志,左下角是选中进程的代码指标,右下角是进程信息。左右方向键切换面板,上下方向键滚动当前面板内容。

注意事项

虽然很高大上,但不可能一直开着面板查看进程信息,当然也很易死机导致面板卡死。另外还有几个细节需注意。
若不为Node进程指定name,则会被pm2自动命名,有一个专用的name就能方便知道哪个Node进程是自己想处理的。
当Node服务迭代开发完毕再上传最新代码,需手动重启Node进程,这样很麻烦,说好的热启动在哪?若Node进程因为某种原因导致内存占用率逐渐变大,会让服务器的运行压力大增,如何是好?
执行pm2 stop 0停止Node进程,再执行pm2 delete 0删除Node进程。改造以下启动命令。

1
pm2 start npm --name data-base --watch --max-memory-restart 300 -- run deploy

通过–name指定服务名称,通过–watch开启监听文件变动重启,通过–max-memory-restart设置当内存占用率超过阈值自动重启。
– run start划重点。执行npm start等同于执行npm run start。使用pm2 start执行npm run start,就是将其拆分为npm与run start,将第一部分存放到pm2 start后,将第二部分使用–连接并存放到末尾。

同理,将npm run build或yarn run build部署到服务器并使用pm2管理,那其命令形式应改成以下形式。

1
2
3
4
5
6
bash
复制代码# npm run build
pm2 start npm --name yangzw --watch --max-memory-restart 300 -- run build

# yarn run build
pm2 start yarn --name yangzw --watch --max-memory-restart 300 -- run build

结语

使用pm2管理Node进程会让开发者变得更省心,同时也更方便管理每个Node进程。在pm2未应用起来前,部署一个Node服务很麻烦,每次版本迭代都要手动处理相关问题,使得部署流程很繁琐。善用pm2能为部署流程变得更方便快捷。