Skip to main content

PM2 单机部署

PM2 是 Node 进程管理器,单机部署的事实标准。轻量、零配置、自带负载均衡。但仅适合单机——多机用 K8s。

一、避坑指南

  1. PM2 是单机工具,不要上 K8s 还在用

    • PM2 管进程不管容器
    • K8s 环境下用 cluster mode 是反模式(让 K8s 做调度)
  2. 必须用 ecosystem 配置文件,不要纯 CLI

    # ❌ 命令行:散乱、不可版本化
    pm2 start app.js -i 4 --name web

    # ✅ 配置文件:commit 到 git
    pm2 start ecosystem.config.js --env production
  3. cluster 模式必须开(多核利用):

    // ecosystem.config.js
    module.exports = {
    apps: [{
    name: "web",
    script: "./dist/server.js",
    instances: "max", // ← 关键:用满所有 CPU 核
    exec_mode: "cluster",
    }],
    };
  4. 零停机重载用 reload 不是 restart

    # ❌ restart 会停掉再起,中间有秒级 downtime
    pm2 restart web

    # ✅ reload 逐个重启(graceful reload)
    pm2 reload web
  5. 日志要分割,否则磁盘会爆:

    pm2 install pm2-logrotate
    pm2 set pm2-logrotate:max_size 10M
    pm2 set pm2-logrotate:retain 30
  6. 开机自启

    pm2 startup        # 生成开机启动命令
    pm2 save # 保存当前进程列表

二、什么时候用 PM2?

场景用 PM2?推荐方案
内部小服务 / 工具首推PM2
中小团队 SSR 服务(单台服务器)首推PM2 + Nginx
内部 Node 后端(1~3 台机器)✅ 推荐PM2 + Nginx
多机 / 弹性扩缩容❌ 改用 K8sK8s / Docker Swarm
纯静态CDN
K8s 集群内部用 K8s 自带机制

决策原则单机 + Node 服务 = PM2。多机或容器化用 K8s。

三、PM2 vs Docker vs K8s

维度PM2DockerK8s
部署粒度进程容器Pod
资源隔离❌(共享 OS)✅ 强✅ 强
负载均衡✅ cluster 内置需外部(Nginx)✅ Service / Ingress
自动恢复✅ 内置restart policy✅ 内置
多机❌ 需手动✅ docker swarm✅ 原生
启动速度< 1s几秒几十秒
学习成本
日志内置需配置需配置(EFK/Loki)
监控pm2 monit / pm2 plus外部外部

典型组合PM2(Node 进程管理) + Nginx(反向代理/SSL)。Docker 也常包一层:Docker 打包 + PM2 进程管理 + Nginx 反代。

四、快速上手

# 全局安装
npm i -g pm2

# 启动应用
pm2 start app.js # 普通启动
pm2 start npm --name "web" -- run start # 启动 npm script

# 查看
pm2 list # 进程列表
pm2 monit # 实时监控(CPU/内存)
pm2 logs # 实时日志
pm2 logs web --lines 100 # 最近 100 行

# 控制
pm2 stop web # 停止
pm2 restart web # 重启(有 downtime)
pm2 reload web # 零停机重载
pm2 delete web # 删除
pm2 delete all # 全部删除

# 信息
pm2 info web # 详细信息
pm2 show web # 同 info

五、ecosystem.config.js 完整配置

// ecosystem.config.js
module.exports = {
apps: [
{
name: "web",
script: "./dist/server.js",
cwd: "/var/www/app",

// 集群模式:用满所有 CPU 核
instances: "max",
exec_mode: "cluster",

// 环境变量
env: {
NODE_ENV: "development",
PORT: 3000,
},
env_production: {
NODE_ENV: "production",
PORT: 3000,
DATABASE_URL: "postgresql://...",
},

// 资源限制
max_memory_restart: "500M", // 内存超 500M 自动重启

// 日志
log_file: "/var/log/pm2/web.log",
error_file: "/var/log/pm2/web-err.log",
out_file: "/var/log/pm2/web-out.log",
merge_logs: true,
log_date_format: "YYYY-MM-DD HH:mm:ss Z",

// 监听文件变化(开发用)
watch: false,
ignore_watch: ["node_modules", ".git", "logs"],

// 优雅关闭
kill_timeout: 5000, // 5s 内 kill 不掉强制 kill
wait_ready: false,
listen_timeout: 8000,

// 自动重启
max_restarts: 10,
min_uptime: "10s", // 运行 10s 内挂掉不计入重启
restart_delay: 1000, // 重启延迟 1s
},
],
};
# 启动(指定环境)
pm2 start ecosystem.config.js --env production

# 重载(用新环境变量)
pm2 reload ecosystem.config.js --env production

六、Cluster 模式(负载均衡)

PM2 cluster 模式 = 内置 Node.js cluster 模块,master 进程把请求分发给 worker。

// ecosystem.config.js
{
instances: 4, // 4 个 worker(或 "max")
exec_mode: "cluster",
}
pm2 start ecosystem.config.js --env production
pm2 list
# ┌────┬──────┬─────────┬──────┬────────┬──────────┐
# │ id │ name │ mode │ ↺ │ status │ cpu │
# ├────┼──────┼─────────┼──────┼────────┼──────────┤
# │ 0 │ web │ cluster │ 0 │ online │ 0% │
# │ 1 │ web │ cluster │ 0 │ online │ 0% │
# │ 2 │ web │ cluster │ 0 │ online │ 0% │
# │ 3 │ web │ cluster │ 0 │ online │ 0% │
# └────┴──────┴─────────┴──────┴────────┴──────────┘

面试题:cluster 模式怎么做到「零停机」? :reload 时 master 逐个重启 worker(先起新的 → 老的才会停),保证任何时刻都有 worker 在线

七、Nginx 反向代理

PM2 监听 127.0.0.1:3000,Nginx 监听 :80/:443

# /etc/nginx/sites-available/myapp
upstream myapp {
server 127.0.0.1:3000;
keepalive 64;
}

server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}

server {
listen 443 ssl http2;
server_name example.com;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

# gzip
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml;

# 反代
location / {
proxy_pass http://myapp;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

八、PM2 部署工作流

# 1. 本地构建
pnpm build
# 2. 同步到服务器
rsync -avz --exclude=node_modules ./dist user@server:/var/www/app/
# 3. 远程 reload
ssh user@server "cd /var/www/app && pm2 reload ecosystem.config.js --env production"

或用 PM2 的 deploy 功能(适合简单项目):

// ecosystem.config.js
module.exports = {
apps: [{ name: "web", script: "./dist/server.js" }],
deploy: {
production: {
user: "deploy",
host: ["1.2.3.4"],
ref: "origin/main",
repo: "git@github.com:myorg/myapp.git",
path: "/var/www/app",
"pre-deploy-local": "",
"post-deploy": "pnpm install --frozen-lockfile && pnpm build && pm2 reload ecosystem.config.js --env production",
"env": { NODE_ENV: "production" },
},
},
};
# 一键部署
pm2 deploy production setup # 初始化
pm2 deploy production # 部署
pm2 deploy production revert 1 # 回滚到上一版

建议复杂项目用 GitHub Actions / GitLab CI,PM2 deploy 适合内部小项目。

九、监控与日志

# 实时监控
pm2 monit

# 内存/重启统计
pm2 list
# 看 ↺ 列(重启次数)、memory 列

# 日志
pm2 logs web # 实时
pm2 logs web --lines 200 # 最近 200 行
pm2 flush # 清空日志

# 性能分析(CPU profile)
pm2 profile web # 录制 30s CPU profile

生产监控推荐

  • pm2 plus(官方 SaaS,付费)
  • Keymetrics / PM2 Plus
  • 接入 Prometheus + Grafana

十、面试高频

Q1:PM2 cluster 模式和 fork 模式区别?

A:

  • fork:单进程(不利用多核)
  • cluster:master + N worker,利用多核 + 内置负载均衡
  • 生产环境必须 cluster

Q2:pm2 restartpm2 reload 区别?

A:

  • restart先停再起,有秒级 downtime
  • reload逐个重启(graceful reload),零停机

生产环境永远用 reload

Q3:怎么保证 PM2 应用崩溃后自动恢复?

A:PM2 内置:

  • max_restarts:最大重启次数
  • min_uptime:运行 N 秒内挂掉才计入重启
  • max_memory_restart:内存超限自动重启
  • 进程崩溃时自动重启

业务死锁(如 DB 连接池耗尽但没崩)PM2 不会发现,需配合健康检查 + 监控告警

Q4:PM2 适合多机部署吗?

A:不适合。PM2 是单机进程管理器。多机用 K8s 或自己写 deploy 脚本(rsync + ssh)。

Q5:为什么不用 nohup / & 启动 Node?

A:nohup / &

  • ❌ 进程崩溃不自动恢复
  • ❌ 不支持 cluster
  • ❌ 不支持日志管理
  • ❌ 不支持监控
  • ❌ 不支持零停机重载

PM2 把这些都包了。生产环境必须用进程管理器

十一、相关文档