Node.js 部署与进程管理完全指南:PM2 实战

小飞兽 Node.js 186 次阅读 2026-07-27

PM2 简介

PM2(Process Manager 2)是 Node.js 生态中最流行的进程管理工具,支持进程守护、负载均衡、日志管理、零配置热重载、远程监控等功能。使用 npm install -g pm2 全局安装。

基础命令

# 启动应用(自动检测入口文件)
pm2 start app.js

# 启动并指定应用名称
pm2 start app.js --name my-api

# 启动带环境变量
pm2 start app.js --name my-api --env production

# 查看进程列表
pm2 list
# 等价于
pm2 status

# 查看详细日志
pm2 logs my-api

# 查看特定行数日志
pm2 logs my-api --lines 50

# 重启应用(先停止再启动)
pm2 restart my-api

# 重新加载(零 downtime,针对集群)
pm2 reload my-api

# 停止应用
pm2 stop my-api

# 删除应用(从 PM2 管理列表中移除)
pm2 delete my-api

# 查看监控面板(实时 CPU/内存)
pm2 monit

# 查看应用详细信息
pm2 show my-api

ecosystem.config.js 配置文件

推荐使用配置文件管理多应用部署:

// ecosystem.config.js
module.exports = {
  apps: [
    {
      // ===== 基本配置 =====
      name: 'my-api',                    // 应用名称
      script: './src/index.js',          // 入口脚本
      args: '--env production',          // 启动参数
      cwd: './',                         // 工作目录

      // ===== 资源限制 =====
      instances: 4,                     // 进程数量(max 表示 CPU 核心数)
      exec_mode: 'cluster',              // 'cluster'(集群)或 'fork'(默认)
      max_memory_restart: '512M',        // 内存超限自动重启

      // ===== 环境变量 =====
      env: {
        NODE_ENV: 'development',
        PORT: 3000
      },
      env_production: {
        NODE_ENV: 'production',
        PORT: 3000
      },

      // ===== 日志配置 =====
      log_file: './logs/combined.log',   // 所有日志
      out_file: './logs/out.log',        // stdout
      error_file: './logs/error.log',    // stderr
      log_date_format: 'YYYY-MM-DD HH:mm:ss',
      merge_logs: true,                  // 多进程日志合并

      // ===== 进程策略 =====
      autorestart: true,                 // 崩溃自动重启
      watch: false,                      // 生产环境关闭 watch
      max_restarts: 10,                  // 最大重启次数
      min_uptime: '10s',                 // 认为正常的最短运行时间
      restart_delay: 4000,               // 重启延迟(毫秒)

      // ===== 其他 =====
      node_args: '--max-old-space-size=4096',  // Node 参数
      source_map_support: true,          // Source Map 支持
      kill_timeout: 5000,                // 等待进程优雅退出的时间
      listen_timeout: 3000               // 应用启动超时
    },

    // 第二个应用示例
    {
      name: 'worker',
      script: './workers/sync.js',
      instances: 2,
      exec_mode: 'fork',
      cron_restart: '0 3 * * *',         // 每天凌晨 3 点重启(定时任务)
      env: {
        NODE_ENV: 'production'
      }
    }
  ]
};

启动命令

# 使用配置文件启动
pm2 start ecosystem.config.js

# 指定环境(--env 参数选择 env_XXX 配置)
pm2 start ecosystem.config.js --env production

# 只启动第一个应用
pm2 start ecosystem.config.js --only my-api

# 启动所有应用
pm2 start ecosystem.config.js --only 'my-api,worker'

集群模式与负载均衡

PM2 的集群模式利用 Node.js 内置的 cluster 模块,实现多进程负载均衡,无需修改代码:

# 启动 4 个进程(自动分配负载)
pm2 start app.js -i 4 --name my-api

# 使用 max 自动匹配 CPU 核心数
pm2 start app.js -i max --name my-api

# 动态调整进程数
pm2 scale my-api +3   # 增加 3 个进程
pm2 scale my-api 8    # 调整为 8 个进程
pm2 scale my-api 0    # 停止所有进程

重要注意:集群模式下,应用需要是无状态的(不存储内存数据),因为不同请求可能被分配到不同进程。Session 和缓存数据必须存储在 Redis 等外部存储中。

Docker 集成

# Dockerfile
FROM node:20-alpine

WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force

COPY . .
COPY .env.production .env

EXPOSE 3000

# 使用 tini 作为 PID 1init 进程,正确处理信号
RUN apt-get update && apt-get install -y tini && rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["/usr/bin/tini", "--"]
CMD ["pm2-runtime", "start", "ecosystem.config.js", "--env", "production"]
# docker-compose.yml
version: '3.8'
services:
  api:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
    env_file:
      - .env.production
    restart: unless-stopped
    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 1G
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

日志管理

# 查看日志(实时追踪)
pm2 logs my-api --lines 100 --nostream

# 日志分割(使用 logrotate)
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 10M       # 单个日志文件最大 10MB
pm2 set pm2-logrotate:retain 7            # 保留 7 个文件
pm2 set pm2-logrotate:compress true       # 压缩旧日志

# 清空日志(不停止应用)
pm2 flush my-api

# 将日志重定向到 syslog
pm2 start app.js --syslog

系统启动脚本

# 生成启动脚本(根据系统 init 方式自动选择)
pm2 startup

# 保存当前进程列表(下次开机自动恢复)
pm2 save

# 查看启动配置命令
pm2 unstartup

# systemd 手动配置示例
# 将以下内容写入 /etc/systemd/system/my-api.service
# [Unit]
# Description=My Node.js API
# After=network.target
#
# [Service]
# Type=simple
# User=ubuntu
# WorkingDirectory=/home/ubuntu/my-api
# ExecStart=/usr/bin/env pm2 start ecosystem.config.js --env production
# Restart=on-failure
# RestartSec=10
# StandardOutput=syslog
# StandardError=syslog
# SyslogIdentifier=my-api
# Environment=NODE_ENV=production
#
# [Install]
# WantedBy=multi-user.target

PM2 Plus 监控(可选)

PM2 Plus 是付费监控服务,提供 Web UI、异常告警、性能指标:

# 本地部署 PM2 Plus
pm2 link <secret-key> <public-key>

# 查看在线仪表盘
pm2 plus

对于免费替代方案,推荐使用:

  • <strong>Prometheus + Grafana</strong> — 自建监控系统

  • <strong>PM2 的内置 API</strong> — <code>pm2 list</code> / <code>pm2 jlist</code> 获取 JSON 格式状态

  • <strong>日志服务</strong> — ELK Stack(Elasticsearch + Logstash + Kibana)

常见问题

Q1: PM2 集群模式和 Nginx 负载均衡哪个更好?

两者可以叠加使用。PM2 集群模式在单台服务器内实现多核利用(利用多核 CPU);Nginx 作为反向代理,在多台服务器间分配流量。建议:小项目(<4 核)只用 PM2 集群;大项目(多台服务器)PM2 集群 + Nginx 负载均衡。

Q2: PM2 重启后数据丢失怎么办?

PM2 的 pm2 save 只能保存进程列表,无法保存应用数据。应用数据必须存储到持久化存储(MySQL、MongoDB、Redis、文件系统等)。PM2 重启不等于应用数据丢失——如果数据丢失,说明设计有问题(内存数据没有定期持久化)。

Q3: 如何排查 PM2 进程崩溃的原因?

1. pm2 logs my-api --err --lines 100 查看错误日志
2. pm2 describe my-api 查看进程详情(重启次数、内存、CPU)
3. pm2 monit 实时观察资源使用
4. 检查 .pm2/pm2.log 中的系统级错误
5. 确保 .pm2/pids/ 中的 PID 与实际进程匹配
6. 检查系统 OOM(Out Of Memory)日志:dmesg | grep -i "out of memory"

延伸阅读

  • <a href="https://pm2.keymetrics.io/docs/usage/quick-start/">PM2 官方文档</a>
  • <a href="https://pm2.io/">PM2 Plus 监控平台</a>
  • <a href="https://expressjs.com/zh-cn/advanced/best-practice-performance.html">Node.js 生产环境最佳实践</a>