PM2 (Process Manager 2) 是一款功能强大的 Node.js 应用程序进程管理器,内置负载均衡功能。 它可以让应用程序常驻后台运行,在程序崩溃时自动重启,并简化了多进程管理、性能监控、日志管理等常见的开发和运维任务。 尽管 PM2 是为 Node.js 设计的,但它也可以管理其他类型的应用程序。

主要特性

  • 进程守护: 能在应用程序崩溃时自动重启,确保服务的高可用性。
  • 负载均衡: 支持集群模式,可以启动多个应用实例来提高性能和可靠性。
  • 日志管理: 方便地查看和管理应用程序的日志。
  • 性能监控: 提供监控功能,跟踪每个进程的 CPU 和内存使用情况。
  • 零停机重载: 可以在不中断服务的情况下重新加载应用程序。
  • 开机自启: 可以配置脚本,在服务器重启后自动启动应用。

常用操作命令

以下是一些 PM2 的常用命令,以功能进行分类:

进程管理

  • pm2 start <app.js>:启动一个应用程序。
    • 可以附加参数,例如:
      • --name <app_name>:为应用指定一个名称。
      • -i <number>:启动指定数量的应用实例(集群模式)。-i max 则会根据 CPU 核心数启动实例。
      • --watch:当文件发生变化时自动重启应用。
  • pm2 stop <app_name|id>:停止指定的应用程序。
  • pm2 restart <app_name|id>:重启指定的应用程序。
  • pm2 reload <app_name|id>:以零停机的方式重新加载应用程序,这在生产环境中非常有用。
  • pm2 delete <app_name|id>:从 PM2 的进程列表中移除指定的应用程序。
  • pm2 listpm2 ls:列出所有由 PM2 管理的应用程序及其状态。

日志管理

  • pm2 logs:显示所有应用程序的实时日志。
  • pm2 logs <app_name|id>:显示指定应用程序的日志。
  • pm2 flush:清空所有的日志文件。

监控与详情

  • pm2 monit:打开一个实时监控面板,显示 CPU 和内存使用情况。
  • pm2 show <app_name|id>pm2 describe <app_name|id>:显示指定应用程序的详细信息。

实现开机自启

为了确保服务器重启后,由 PM2 管理的应用能够自动恢复运行,需要配置开机自启。

  • pm2 startup:生成在系统启动时运行 PM2 的脚本。这是实现开机自启的关键,通常只需要配置一次。
  • pm2 save:保存当前 PM2 管理的进程列表。
  • pm2 resurrect:手动恢复由 pm2 save 保存的进程列表。如果未设置 startup 脚本,可在服务器重启后手动执行此命令。

查看已保存的列表

pm2 save 命令会将当前的进程列表保存到一个名为 dump.pm2 的 JSON 文件中。要查看其内容,您可以使用任何文本编辑器打开此文件。

该文件通常位于 PM2 的主目录下:

  • Linux / macOS: ~/.pm2/dump.pm2
  • Windows: C:\Users\<你的用户名>\.pm2\dump.pm2 (也可以在文件资源管理器中通过 %USERPROFILE%\.pm2 快速访问)

这个文件详细记录了被保存的每个应用的配置信息,pm2 resurrect 正是依据此文件来恢复应用的。

工作流程

要让应用在服务器重启后自动恢复,通常需要两步:

  1. 设置启动脚本:执行 pm2 startup。系统会提示运行一个命令,将其复制并执行即可。这会将 PM2 设置为开机自启服务。
  2. 保存进程列表:每当更新了进程列表(例如,启动了新应用或删除了应用)后,执行 pm2 save。这个命令会将当前的进程状态保存下来。

完成以上步骤后,服务器重启时,pm2 startup 设置的服务会自动运行,并加载 pm2 save 保存的进程列表,从而实现应用的自动恢复。

使用配置文件 (ecosystem.config.js)

对于管理多个应用或复杂配置的场景,使用配置文件是 PM2 的最佳实践。这不仅能让配置一目了然,还能轻松实现多环境部署。

  • pm2 ecosystem:在当前目录下生成一个示例配置文件 ecosystem.config.js,可以在其中定义应用程序的各种运行参数。

配置完成后,可以通过 pm2 start ecosystem.config.js (或简写为 pm2 start) 来启动文件中定义的所有应用。

Node.js 服务示例

对于 Node.js 应用,配置非常直接。以下是一个常见的配置,定义了应用名称、启动脚本、实例数量、环境变量等。

// ecosystem.config.js
module.exports = {
  apps: [{
    // 应用名称
    name: 'my-node-app',
    // 启动脚本路径
    script: './bin/www',
    // 实例数量。
    // 设置为 1 是 Fork 模式(单进程);设置为 'max' 或大于 1 的数字会开启集群模式,以利用多核 CPU 性能。
    instances: 1,
    // 发生错误时是否自动重启。
    // 默认设置为 false 可避免在开发或修复阶段,因代码错误导致无限重启循环。
    // 在生产环境中,强烈建议设置为 true,并配合下面的 `exp_backoff_restart_delay` 来增强稳定性。
    autorestart: false,
    // 固定重启延迟(毫秒)。
    // 此配置会在每次重启前(无论何种原因)都等待一个固定的时间。
    // 适用于需要时间释放端口或资源的应用,但对于防止崩溃循环不如 `exp_backoff_restart_delay` 智能。
    restart_delay: 50,
    // 指数退避重启延迟(毫秒)。
    // 此配置仅在 `autorestart: true` 时生效。
    // 当应用在短时间内频繁崩溃时,PM2 会自动延长每次重启间的等待时间,防止“崩溃重启循环”耗尽系统资源。
    // 例如,第一次重启延迟 0ms,第二次 100ms,第三次 200ms,以此类推,直到达到一个最大值。
    exp_backoff_restart_delay: 100,
    // 是否启用文件监控。如果为 true,则文件变化时会自动重启应用。
    watch: false,
    // 监控延迟(毫秒),即文件变化后等待多久才重启,以防止频繁重启。
    watch_delay: 1000,
    // 监控时忽略的文件或目录列表,支持正则表达式。
    ignore_watch: ['node_modules', 'logs', 'public'],
    // 日志文件的时间戳格式。
    log_date_format: 'YYYY-MM-DD HH:mm:ss',
    // 当内存超过 1G 时重启
    max_memory_restart: '1G',
    // 默认环境变量
    // 当执行 `pm2 start` (隐式) 或 `pm2 start ecosystem.config.js` (显式) 且不带 `--env` 参数时加载。
    env: {
      NODE_ENV: 'development',
      PORT: 3000
    },
    // 开发环境变量
    // 当执行 `pm2 start --env development` 或 `pm2 start ecosystem.config.js --env development` 时加载。
    env_development: {
      NODE_ENV: 'development',
      PORT: 3001 // 使用不同端口以作区分
    },
    // 生产环境变量
    // 当执行 `pm2 start --env production` 或 `pm2 start ecosystem.config.js --env production` 时加载。
    env_production: {
      NODE_ENV: 'production',
      PORT: 80
    }
  }]
};

实例数量配置(instances) 可以参考《Node.js 部署:PM2 的 Fork 与集群模式》,里面有更详尽的解释。

Java 服务示例

PM2 也可以管理非 Node.js 应用,例如 Java 的 .jar 包。关键在于正确设置 scriptargs,并使用 fork 模式。

// ecosystem.config.js
module.exports = {
  apps: [{
    // 应用名称
    name: 'my-java-app',
    // 要执行的命令
    script: 'java',
    // 传递给 java 命令的参数。
    // Spring Boot 配置可以通过命令行参数传入,例如:--spring.profiles.active=prod
    // 通过命令行参数设置配置的方式,其优先级高于下面的 `env` 环境变量。
    args: '-jar /path/to/your/app.jar --server.port=8080',
    // 只启动一个实例
    instances: 1,
    // 使用 fork 模式,而不是 cluster 模式
    exec_mode: 'fork',
    // 标准输出日志文件的路径。
    // 设置为 /dev/null 可以忽略所有标准输出。
    out_file: './logs/out.log',
    // 错误输出日志文件的路径。
    // 设置为 /dev/null 可以忽略所有错误输出。
    error_file: './logs/error.log',
    // 当内存超过 2G 时重启
    max_memory_restart: '2G',
    // 环境变量。
    // 这是设置 Spring Boot 配置的另一种方式,PM2 会将这些变量注入到进程环境中。
    // Spring Boot 会自动识别 SPRING_PROFILES_ACTIVE 并将其映射为 spring.profiles.active。
    // 推荐使用此方法,以便利用 PM2 的多环境配置。
    // 与 Node.js 示例中的 `env` 块一样,此 `env` 块在执行 `pm2 start` 或 `pm2 start ecosystem.config.js` 时加载。
    env: {
      SPRING_PROFILES_ACTIVE: 'prod'
    }
    // 其它配置可以参考上述“Node.js 服务示例”
  }]
};

更多推荐