Skip to content

监控、内存保护与重启策略

定位:回答两类问题——"现在服务健不健康"(监控)"挂了之后 PM2 到底按什么规矩重启"(策略)
一句话总纲:PM2 只管"进程死活 + 资源统计 + 按策略重启";告警与健康检查要自己搭

读懂 pm2 ls

bash
pm2 ls

输出表格各列(5.x 起基本一致):

含义怎么用
name应用名管理入口
id进程编号脚本内精确操作
modefork / cluster判断部署形态
(restarts)重启次数>0 就说明发生过崩溃/被杀/重启
statusonline/stopped/errored/…第一眼健康度
cpu实时 CPU%(瞬时值)毛刺排查
memory实时内存占用看是否有上涨趋势
uptime已运行时长配合 ↺:刚重启过会很小

读表心法status 决定"活着没"; 决定"稳不稳";memory 决定"要不要加保护/排查泄漏"。

深入单进程:pm2 describe

bash
pm2 describe api

它给出一个进程的"全息档案",排查必看字段:

  • 身份与状态:statusnameidnamespace
  • 重启历史:restartsunstable restarts(不稳定重启次数)、created atexit code(上次退出的退出码)
  • 启动方式:script pathscript argsexec cwdexec modeinterpreternode argswatchcron restart
  • 资源护栏:max memory restart
  • 日志/文件:out log patherror log pathpid path
  • 环境:env(可确认 NODE_ENV 到底注入没)

排查"这个进程到底怎么被拉起来的"——答案全在 describe 里,比猜强一百倍。

进程状态与"稳定"判定

status 常见取值见 核心概念 §5。这里补两个高频概念:

  • errored 不等于"代码 bug 被捕获显示":它表示进程起不来(如端口占用、语法错误)或重启策略已放弃继续拉。根因去应用日志找。
  • unstable(不稳定):进程反复在短时间内崩溃→重启,PM2 会认为"再拉也没用",按策略停止并标记,避免无限空转烧 CPU。

内存保护:max_memory_restart

bash
# CLI
pm2 start app.js --max-memory-restart 512M
# ecosystem
max_memory_restart: '512M'
  • 语义:PM2 周期性采样进程内存(官方口径:内存检查 worker 约每 30s 跑一次),超过阈值即重启该进程(计入 restart)。
  • 单位写法:512M1G100K;也可写纯数字(默认单位字节,不推荐,易错)。
  • 典型值:Node 默认堆上限约 2GB(老版本 1.5GB)场景下,业务常设 512M1G
  • 定位:它是"止损"护栏,不是"修泄漏"的药。若看到它频繁触发,请查应用内存泄漏(heap snapshot、--node-args "--max-old-space-size" 调优等)。

采样是"周期性的",不是纳秒级硬限制;突刺超限不一定会立刻触发。

重启策略字段全解

以下字段决定"崩了之后怎么拉、拉几次、隔多久"(ecosystem 写法,默认值以官方文档为准):

字段含义典型用法
autorestart异常退出后是否自动重启(默认 true)跑一次性任务设 false
max_restarts“不稳定重启”次数的保护上限(默认 16)频繁崩溃时防止无限重启
min_uptime一次“稳定运行”的最小时长:活过它才算一次稳定启动启动慢的应用调大它,避免被误判不稳定
restart_delay每次重启前固定等待(ms)依赖下游就绪时给缓冲
exp_backoff_restart_delay指数退避重启:首间隔=设定值,逐次翻倍,封顶 15s;稳定运行 >30s 后重置连崩时避免雪崩式重启
cron_restartcron 定时整点重启(需进程正在运行才生效;如 '0 0 * * *'每天低峰清理长驻进程

判定“不稳定”的逻辑(官方口径):重启间隔小于 1s(或小于你设的 min_uptime)的连续重启被计为“不稳定重启”;达到 max_restarts(默认 16)后 PM2 停止自动重启、状态转 errored——这是保护机制,不是 bug。指数退避期间,进程状态会显示 waiting restart

配置建议

  • 常规服务:autorestart:true + restart_delay: 1000~3000,避免下游未就绪时的连崩;
  • 依赖外部强、启动慢的服务:调大 min_uptime / 用 wait_ready集群模式与零停机发布);
  • 不想在流量高峰被"反复拉死"的:exp_backoff_restart_delay: 100 + max_restarts 收敛。

监控与告警怎么搭

先认清边界:PM2 只给你"看"的能力(list/monit/describe/jlist)和"策略执行"(重启)。它默认不会主动报警(没有短信/钉钉/邮件通道)。想告警,有几种路线:

路线 1:命令/API 自建巡检(零成本,自控)

PM2 提供机器可读输出,写个 cron/脚本轮询即可:

bash
pm2 jlist         # 全部进程信息 JSON(每行一条),脚本最爱
pm2 prettylist    # 格式化 JSON

示例思路(伪代码):

js
// health-check.js:每 1 分钟跑一次,异常就发告警
const procs = JSON.parse(execSync('pm2 jlist').toString());
for (const p of procs) {
  if (p.pm2_env.status !== 'online')  alert(`${p.name} 不在线!`);
  if (p.pm2_env.restart_time > 5)     alert(`${p.name} 重启次数异常`);
  if (p.monit.memory > 600 * 1024 * 1024) alert(`${p.name} 内存过高`);
}

用 systemd timer 或 crontab 调度,把 alert() 换成 webhook(钉钉/飞书/Slack)。

路线 2:官方托管面板 pm2.io(原 Keymetrics / PM2 Plus)

  • PM2 自带了遥测/指标 agent(@pm2/io),可接入官方托管服务 app.pm2.io:web 仪表盘、历史曲线、重启告警、异常捕获等。
  • 需要注册账号并在本机 pm2 link/配置(免费额度存在,商用条款以官方为准)。
  • 若团队不允许数据出内网,此路线不可用,回到路线 1 或 3。

路线 3:接入既有监控体系

  • Prometheus 生态:社区有把 pm2 jlist/@pm2/io 指标导出到 Prometheus 的 exporter,配合 Grafana 面板;
  • 或者直接把进程信息打进应用自身的 metrics 端点(/metrics),由应用暴露,与 PM2 无关但更灵活。

结论:小项目 → 路线 1 的脚本 + 日志轮转就够;大项目 → 用监控体系统一收,PM2 只管把进程和指标喂出来。

小结:让 PM2 真正"省心"的三件套

js
// ecosystem.config.js
{
  name: 'api',
  script: 'app.js',
  max_memory_restart: '512M',   // 1) 内存护栏
  autorestart: true,
  restart_delay: 2000,          // 2) 崩了等 2s 再拉,别连崩
  exp_backoff_restart_delay: 100,
  max_restarts: 16,             // 3) 连崩保护(默认 16),别无限空转
}

配上外部巡检脚本(路线 1)与日志轮转(日志与轮转),一台机器的单应用托管基本就齐了。

参考链接