PM2 进程管理实战:集群模式、日志管理与生产部署

PM2 是 Node.js 生态里用得最多的进程管理工具,不只是后台运行,还有负载均衡、日志管理、监控告警、自动重启这些生产级功能。这篇记录 PM2 的核心用法、集群模式配置、Keymetrics 监控接入,以及生产环境的一些经验。

PM2 核心功能概览

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
┌─────────────────────────────────────────────────────────────────────┐
│ PM2 核心功能架构 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ PM2 Daemon (守护进程) │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ • 进程管理 (start/stop/restart/delete) │ │
│ │ • 集群模式 (Cluster Mode) │ │
│ │ • 自动重启 (Auto Restart) │ │
│ │ • 日志管理 (Log Management) │ │
│ │ • 环境变量 (Environment Variables) │ │
│ │ • 开机自启 (Startup Script) │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────┼────────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Worker 1│ │ Worker 2│ │ Worker N│ │
│ │ :3000 │ │ :3001 │ │ :300N │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ Keymetrics (云端监控) │
│ • 实时 CPU/内存监控 │
│ • 异常告警 │
│ • 在线日志查看 │
│ │
└─────────────────────────────────────────────────────────────────────┘

安装与基础命令

全局安装

1
npm install -g pm2

核心命令速查表

命令 作用
pm2 start app.js 启动应用
pm2 start app.js -i 4 启动 4 个集群实例
pm2 start app.js --name api 指定进程名称
pm2 list 查看所有进程状态
pm2 monit 打开实时监控面板
pm2 logs 查看所有进程日志
pm2 stop all 停止所有进程
pm2 restart all 重启所有进程
pm2 reload all 0 秒停机重载(集群模式)
pm2 delete all 删除所有进程
pm2 startup 生成开机启动脚本
pm2 save 保存当前进程列表

进程启动方式

基础启动

1
2
3
4
5
6
7
8
9
10
11
# 启动单个实例
pm2 start app.js

# 指定进程名称
pm2 start app.js --name my-api

# 指定环境变量
pm2 start app.js --name my-api --env production

# 传递参数给应用
pm2 start app.js -- --port 3000 --env prod

集群模式启动

1
2
3
4
5
6
7
8
9
10
11
# 根据 CPU 核心数启动最大进程数
pm2 start app.js -i max

# 启动 3 个进程实例
pm2 start app.js -i 3

# 使用 Fork 模式(单实例)
pm2 start app.js -x

# Fork 模式传递参数
pm2 start app.js -x -- -a 23
模式 参数 适用场景
Cluster -i max / -i N HTTP 服务,需要多核利用
Fork -x 后台任务、定时脚本

使用配置文件启动

创建 ecosystem.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
module.exports = {
apps: [
{
name: 'api-server',
script: './server.js',
instances: 'max', // 根据 CPU 数启动
exec_mode: 'cluster', // 集群模式
env: {
NODE_ENV: 'development',
PORT: 3000
},
env_production: {
NODE_ENV: 'production',
PORT: 80
},
log_file: './logs/combined.log',
out_file: './logs/out.log',
error_file: './logs/error.log',
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
max_memory_restart: '500M', // 内存超 500MB 自动重启
restart_delay: 3000, // 重启间隔 3 秒
max_restarts: 10, // 最大重启次数
min_uptime: '10s', // 最小运行时间
watch: false, // 生产环境关闭文件监控
ignore_watch: ['node_modules', 'logs'],
merge_logs: true, // 集群模式合并日志
kill_timeout: 5000 // 优雅关闭超时 5 秒
},
{
name: 'worker',
script: './worker.js',
instances: 1,
exec_mode: 'fork',
cron_restart: '0 2 * * *' // 每天凌晨 2 点重启
}
]
};

启动:

1
2
pm2 start ecosystem.config.js
pm2 start ecosystem.config.js --env production

集群模式详解

为什么使用集群模式

Node.js 是单线程的,默认只能利用一个 CPU 核心。通过 PM2 的集群模式,可以在同一台服务器上运行多个 Node.js 进程,充分利用多核 CPU:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
┌─────────────────────────────────────────────────────────────────────┐
│ 集群模式工作原理 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 用户请求 │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Nginx/ │ 负载均衡(可选) │
│ │ PM2 │ │
│ └──────┬──────┘ │
│ │ │
│ ┌─────┼─────┬─────────┐ │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ ┌───┐ ┌───┐ ┌───┐ ┌───┐ │
│ │P1 │ │P2 │ │P3 │ │P4 │ 4 个 Node.js Worker 进程 │
│ │:80│ │:80│ │:80│ │:80│ 共享同一端口(由 PM2 负载均衡) │
│ └───┘ └───┘ └───┘ └───┘ │
│ │
│ 优势: │
│ • 充分利用多核 CPU │
│ • 进程崩溃自动重启,不影响其他进程 │
│ • 0 秒停机重载(reload) │
│ │
└─────────────────────────────────────────────────────────────────────┘

集群模式通信

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// server.js
const cluster = require('cluster');
const http = require('http');

if (cluster.isMaster) {
// 主进程逻辑
console.log(`Master ${process.pid} is running`);

// 监听工作进程消息
for (const id in cluster.workers) {
cluster.workers[id].on('message', (msg) => {
console.log('Message from worker:', msg);
});
}
} else {
// 工作进程逻辑
http.createServer((req, res) => {
res.writeHead(200);
res.end(`Hello from worker ${process.pid}\n`);
}).listen(3000);

console.log(`Worker ${process.pid} started`);
}

0 秒停机重载

1
2
3
4
5
6
7
8
# 普通重启:先停后启,有短暂服务中断
pm2 restart all

# 重载:逐个替换进程,无停机时间
pm2 reload all

# 重载指定应用
pm2 reload api-server
命令 过程 影响
restart 先全部停止,再全部启动 有短暂中断
reload 逐个替换工作进程 无停机,推荐生产使用

日志管理

日志配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 查看实时日志(所有进程)
pm2 logs

# 查看指定进程日志
pm2 logs api-server

# 查看最近 200 行日志
pm2 logs api-server --lines 200

# 清空所有日志
pm2 flush

# 日志轮转配置
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 100M
pm2 set pm2-logrotate:retain 10

pm2-logrotate 配置

1
2
3
4
5
6
7
8
# 安装日志轮转模块
pm2 install pm2-logrotate

# 配置参数
pm2 set pm2-logrotate:max_size 100M # 单日志文件最大 100MB
pm2 set pm2-logrotate:retain 10 # 保留 10 个历史文件
pm2 set pm2-logrotate:compress true # 压缩历史日志
pm2 set pm2-logrotate:dateFormat YYYY-MM-DD_HH-mm-ss

Keymetrics 云端监控

注册与连接

Keymetrics 是 PM2 官方提供的云端监控平台,提供可视化的性能监控和异常告警。

1
2
3
4
5
6
# 1. 在 https://app.keymetrics.io 注册账号并创建 bucket

# 2. 获取 Public Key 和 Secret Key

# 3. 连接 PM2 到 Keymetrics
pm2 link <public_key> <secret_key>

Docker 方式使用 Keymetrics

1
2
3
4
5
docker run -p 80:80 \
-v my_app:/app \
keymetrics/pm2 \
-e "KEYMETRICS_PUBLIC=your_public_key" \
-e "KEYMETRICS_SECRET=your_secret_key"

端口要求

端口 协议 用途
80 TCP 推送指标协议
43554 TCP 反向交互协议(远程控制)

监控面板功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
┌─────────────────────────────────────────────────────────────────────┐
│ Keymetrics 监控面板功能 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 实时监控: │
│ • CPU 使用率趋势图 │
│ • 内存占用趋势图 │
│ • 请求吞吐量(TPS) │
│ • 平均响应时间 │
│ │
│ 异常告警: │
│ • 进程崩溃通知(邮件/Slack) │
│ • 内存溢出告警 │
│ • 响应时间超标告警 │
│ │
│ 日志管理: │
│ • 在线查看实时日志 │
│ • 历史日志检索 │
│ │
│ 远程操作: │
│ • 远程重启进程 │
│ • 远程执行命令 │
│ │
└─────────────────────────────────────────────────────────────────────┘

开机自启配置

生成启动脚本

1
2
3
4
5
6
7
8
9
10
# 根据当前系统自动生成启动脚本
pm2 startup

# 示例输出(CentOS 7):
# sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 \
# startup systemd -u root --hp /root

# 执行输出的命令
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 \
startup systemd -u your-user --hp /home/your-user

保存进程列表

1
2
3
4
5
# 保存当前运行的进程列表
pm2 save

# 保存后,系统重启时会自动恢复这些进程
# PM2 通过读取 ~/.pm2/dump.pm2 文件恢复

验证开机自启

1
2
3
4
5
6
# 查看 systemd 服务状态
sudo systemctl status pm2-root

# 手动测试恢复
pm2 kill # 停止 PM2
pm2 resurrect # 从 dump.pm2 恢复(系统重启时自动调用)

生产环境最佳实践

1. 使用 ecosystem 配置文件

将所有配置集中管理,避免命令行参数混乱:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// ecosystem.config.js
module.exports = {
apps: [{
name: 'api',
script: './server.js',
instances: 'max',
exec_mode: 'cluster',
env_production: {
NODE_ENV: 'production'
},
error_file: './logs/err.log',
out_file: './logs/out.log',
max_memory_restart: '1G',
restart_delay: 3000
}]
};

2. 配合 Nginx 反向代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
upstream nodejs {
server 127.0.0.1:3000;
server 127.0.0.1:3001;
server 127.0.0.1:3002;
server 127.0.0.1:3003;
}

server {
listen 80;
server_name api.example.com;

location / {
proxy_pass http://nodejs;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}

3. 健康检查端点

1
2
3
4
5
6
7
8
9
// 在应用中实现健康检查
app.get('/health', (req, res) => {
res.status(200).json({
status: 'ok',
uptime: process.uptime(),
memory: process.memoryUsage(),
pid: process.pid
});
});

总结

PM2 生产部署的一些经验:

  1. 集群模式:用 -i max-i N 启动多个工作进程,充分利用多核 CPU
  2. 配置文件:用 ecosystem.config.js 管理配置,方便版本控制和团队协作
  3. 日志管理:装 pm2-logrotate 模块做日志自动轮转,防止磁盘占满
  4. 监控告警:接入 Keymetrics 做云端监控,及时发现异常
  5. 开机自启:执行 pm2 startuppm2 save 确保服务随系统启动
  6. 优雅重启:生产环境用 pm2 reload 实现 0 秒停机更新

合理的 PM2 配置能让 Node.js 应用在生产环境中稳定、高效地运行。