想象一下,你写了一个完美的 Node.js 应用。它运行得很棒,直到某个凌晨 3 点,一个未捕获的异常让它崩溃了。然后?沉默。你的服务下线了,用户愤怒了,你的 pagerduty 开始尖叫。
这就是为什么你需要 PM2。
PM2 是什么?
PM2 是一个高级的进程管理器。它不是在运行你的应用,而是在管理你的应用进程。就像一个永不睡觉的运维工程师,盯着你的服务,确保它活着、健康、并且不会因为某个愚蠢的错误而崩溃。
但 PM2 不是保姆。它不会帮你写代码,也不会原谅你的 bug。它只是确保你的 bug 不会把整个服务拖垮。
为什么需要进程管理器?
Node.js 有几个"优秀"的特性:
- 单线程:一个请求阻塞了,整个应用都得等着
- 一挂全挂:任何未捕获的异常都会让进程直接退出
- CPU 利用率低:只能用到一个 CPU 核心,其他核心在旁边围观
PM2 解决了这些问题,而且解决得相当优雅。
PM2 能做什么?
1. 自动重启
你的应用崩溃了?PM2 在毫秒级内把它拉起来。你可以配置重启策略,甚至限制重启次数防止恶性循环。
2. Cluster 模式
充分利用多核 CPU。PM2 自动 fork 多个子进程,共享同一个端口。一个进程挂了?其他进程继续工作。这就是真正的负载均衡。
3. 零停机重载
更新代码时,PM2 会逐个重启进程,确保总有一部分进程在响应用户请求。生产环境的救星。
4. 日志管理
所有日志统一管理,支持自动轮转。你不用再担心日志文件撑爆磁盘。
5. 监控
实时查看 CPU、内存、日志等指标。比盯着控制台舒服多了。
实战:一个完整的 PM2 配置
来看看一个实用的 ecosystem.config.js 脚本:
module.exports = {
apps: [
{
name: 'my-api',
script: './src/index.js',
instances: 'max',
exec_mode: 'cluster',
autorestart: true,
watch: false,
max_memory_restart: '1G',
env: {
NODE_ENV: 'development',
PORT: 3000
},
env_production: {
NODE_ENV: 'production',
PORT: 80
},
log_date_format: 'YYYY-MM-DD HH:mm:ss',
error_file: './logs/app-error.log',
out_file: './logs/app-out.log',
log_file: './logs/combined.log',
merge_logs: true,
time: true,
kill_timeout: 5000,
wait_ready: true,
listen_timeout: 10000,
shutdown_with_message: true
}
]
};
这个脚本做了什么?
- instances: 'max':根据 CPU 核心数自动创建最大数量的实例
- exec_mode: 'cluster':启用 cluster 模式,自动负载均衡
- env 和 env_production:不同环境的不同配置
- max_memory_restart: '1G':内存超过 1GB 自动重启,防止内存泄漏
- watch:文件变化自动重启(生产环境建议关闭)
- wait_ready:等待应用发送 ready 信号后再完成启动
如何使用
# 启动(使用默认环境)
pm2 start ecosystem.config.js
# 启动(使用生产环境)
pm2 start ecosystem.config.js --env production
# 查看状态
pm2 list
# 监控
pm2 monit
# 查看日志
pm2 logs
# 重启
pm2 restart my-api
# 停止
pm2 stop my-api
# 删除
pm2 delete my-api
什么时候该用 PM2?
✅ 生产环境部署
✅ 需要 24/7 可用的服务
✅ 多核 CPU 服务器
✅ 需要日志集中管理
✅ 希望能安心睡觉的开发者
❌ 本地开发调试(虽然可以用,但通常没必要)
❌ 单次运行的脚本任务