在将 Node.js 应用部署到生产环境后,仅仅依靠 pm2 start app.js 保持进程存活是远远不够的。一个稳定的线上服务还需要可靠的进程监控手段、应对内存泄漏的自动止损机制,以及同时管理多个服务时的工程化配置方式。PM2 在这三个方面提供了直接内置的能力,无需引入额外的外部系统。
1. 监控:实时掌握进程与资源状态
PM2 提供了一组轻量但实用的命令行监控工具,可以帮助开发者快速了解进程的运行情况:
(1)进程列表与基础信息
pm2 list
该命令会列出所有由 PM2 管理的进程,默认包含以下字段:
- id:PM2 内部的进程编号,用于 restart / stop / delete 等命令。
- name:应用名称(可在启动时通过
--name指定)。 - mode:运行模式,
fork或cluster。 - status:进程状态,
online、stopped、errored等。 - cpu 与 mem:当前占用的 CPU 百分比与实际内存(如 48.2 MB)。
- uptime:进程自启动以来的运行时长。
出现异常时,这些数据能够帮助快速判断是否某个进程出现了内存持续上涨、频繁重启或 CPU 异常占用等问题。
(2)实时终端仪表盘
pm2 monit
执行后会进入一个基于终端的实时监控界面,分左右两栏:
- 左侧列出所有被管理的进程,实时刷新 CPU 和内存占用。
- 右侧展示当前选中进程的详细日志流。
这个内置面板非常适合在无外接监控系统的临时排查场景下,快速观察业务的资源消耗趋势。
(3)日志管理
PM2 会自动收集每个应用的标准输出和标准错误日志,并存入 ~/.pm2/logs/ 目录下,文件名为 <app-name>-out.log 和 <app-name>-error.log。常用日志相关命令包括:
pm2 logs # 实时查看所有应用的日志(类似 tail -f)
pm2 logs app-name # 只看指定应用
pm2 logs --lines 200 # 查看最近 200 行
pm2 flush # 清空所有日志
此外,可以通过 pm2-logrotate 插件实现日志按大小或日期自动分割和归档,避免日志文件无限增大占满磁盘。
(4)PM2 Plus 在线监控(可选)
对于需要持久化监控数据、多服务器统一管理、自定义告警的团队,PM2 提供了商业化的在线服务 PM2 Plus(以前称为 Keymetrics)。连接后可以在 Web 界面上看到详细的 CPU、内存、请求延迟等指标曲线,并配置 CPU 超限或内存异常告警。不过,对于中小型项目而言,使用 pm2 monit 配合命令行告警脚本往往已经足够。
2. 内存溢出重启:为内存泄漏提供底线防护
Node.js 应用中,内存泄漏可能由于闭包未正确释放、全局缓存不断增长、事件监听器未移除等原因出现。即使测试阶段未能完全暴露,生产环境长时间运行后也可能逐渐积累,最终导致进程内存占用超过服务器上限而崩溃。
PM2 提供了一个非常关键的配置项 --max-memory-restart,用于设置进程内存使用上限。当进程占用内存超过此阈值时,PM2 会自动重启该进程:
pm2 start app.js --max-memory-restart 500M
此命令表示当 app.js 进程的内存占用超过 500 MB 时,PM2 会杀死该进程并立即重新启动一个新的实例。
使用建议:
- 阈值的设定应根据应用的正常内存水位来确定。一般设置为正常峰值的 1.5 ~ 2 倍。例如,如果服务日常内存占用在 200 ~ 300 MB,可以配置为 500M 或 600M。
- 该重启机制相当于为内存泄漏兜底,但它并不能替代定位和修复根本问题。在生产环境中应结合
pm2 monit和heapdump等内存分析工具逐步排查泄漏源头。 - 对于采用 cluster 模式的多进程实例,PM2 会单独监控每个子进程的内存,任一子进程超限都会触发该子进程的重启,而不会影响其它子进程。这保证了整体服务的可用性。
配置文件中的写法(推荐):
// ecosystem.config.js
module.exports = {
apps: [
{
name: 'api-service',
script: './app.js',
max_memory_restart: '500M',
instances: 2,
exec_mode: 'cluster'
}
]
};
3. 多项目管理:用一份配置文件统一管理多个进程
当服务器上需要同时运行多个 Node.js 服务(如 API 服务、定时任务、消息消费者等)时,使用多个 pm2 start 命令会变得难以维护和快速启动。此时应当使用 PM2 的 Ecosystem 配置文件 来集中声明所有应用。
(1)快速生成配置文件
pm2 ecosystem
该命令会在当前目录生成一个 ecosystem.config.js 模板文件,其中 apps 数组可以写入多个进程的配置:
module.exports = {
apps: [
{
name: 'api-server',
script: './server.js',
instances: 2,
exec_mode: 'cluster',
env: {
NODE_ENV: 'production',
PORT: 3000
},
max_memory_restart: '400M',
error_file: './logs/api-error.log',
out_file: './logs/api-out.log'
},
{
name: 'cron-worker',
script: './cron.js',
instances: 1,
exec_mode: 'fork',
cron_restart: '0 3 * * *', // 每天凌晨3点重启定时任务
max_memory_restart: '200M'
},
{
name: 'queue-consumer',
script: './consumer.js',
instances: 3,
exec_mode: 'fork',
max_memory_restart: '300M'
}
]
};
(2)一键启动、重启与停止
有了配置文件后,就可以通过一条指令管理所有应用:
pm2 start ecosystem.config.js # 启动所有应用
pm2 restart ecosystem.config.js # 重启所有应用
pm2 stop ecosystem.config.js # 停止所有应用
pm2 delete ecosystem.config.js # 从 PM2 列表中移除所有应用
如果需要只操作其中某一个应用,可以通过 --only 参数指定名称:
pm2 restart ecosystem.config.js --only api-server
多项目管理本质上是对 apps 数组的声明式管理。开发人员可以将该配置文件加入版本库,这样任何团队成员在新服务器上部署时,只需要运行 pm2 start ecosystem.config.js 即可恢复整套后台服务。这个方式极大地降低了因手动逐一启动进程而导致的遗漏或配置不一致的问题。
(3)多项目环境下的一些最佳实践
- 明确命名规则:为每个应用命名时加入项目前缀或角色标识,如
project-a-api、project-b-worker,避免混淆。 - 日志路径隔离:为不同应用指定独立的日志文件路径,或者在配置中定义不同的
error_file和out_file,便于问题追溯。 - 资源上限差异化:根据每个应用的实际负载分别设置
max_memory_restart,防止一个应用的泄漏触发重启,影响同配置文件下的其他进程。 - 启用开机自启:通过
pm2 startup并执行输出的系统命令,使 PM2 随系统启动,再运行pm2 save保存当前进程列表,即可实现服务器重启后所有项目自动恢复。
这三个 PM2 内置能力形成一个完整的生产级进程管理闭环:监控让运维对服务运行状况有直观感知,内存溢出重启提供了自动止损的底线保护,多项目管理则让复杂服务集群的部署与维护变得工程化、规范化。熟练运用它们,是在没有 Kubernetes 等高级编排平台的情况下,也能将 Node.js 服务稳定运行在生产环境的关键。