当前位置:首页 > 虚拟主机 > 正文

pm2如何配置才能持久运行,pm2配置教程

生产环境下的 PM2 配置,不应停留在命令行参数层面,而应使用 ecosystem.config.js 声明式配置,将进程守护、内存限制、日志轮转、优雅重启和集群负载做统一管理,配合云服务器自身的监控与快照能力,才能达到真正意义上的 7×24 小时高可用。

为什么必须使用 PM2 配置文件

直接使用 pm2 start app.js -i max 虽然能快速启动应用,但存在三个致命问题:

  • 启动参数无法持久化,服务器重启后丢失。
  • 环境变量和日志规则散落在脚本中,难以追溯。
  • 无法精细控制错误重启策略和内存阈值,容易引发雪崩。

而 ecosystem.config.js 将所有运维意图代码化,一个文件就能复现整个部署环境,这才是面试和工作中被反复强调的最佳实践。

ecosystem.config.js 核心配置逐项拆解

一个典型的 Node.js 应用配置如下:

module.exports = { apps: [{ name: 'coolfan-api', script: './src/server.js', instances: 'max', exec_mode: 'cluster', max_memory_restart: '512M', error_file: '/data/logs/pm2/err.log', out_file: '/data/logs/pm2/out.log', merge_logs: true, log_date_format: 'YYYY-MM-DD HH:mm:ss', env: { NODE_ENV: 'production', PORT: 3000 }, kill_timeout: 5000, listen_timeout: 8000, restart_delay: 3000, max_restarts: 10 }] };

进程模型与资源控制

  • instances 与 exec_mode:配合使用才能启动集群模式。instances: 'max' 会启用 CPU 全部核心,实现真正的负载均衡,内存限制 max_memory_restart 建议设置为主机物理内存的 1/4 到 1/3,防止内存泄漏拖垮整机。

日志管理的进阶做法

默认的 console.log

写入 PM2 自带日志,但日志不会自动切割,半年后可能占用几十 GB 磁盘,必须配置 log_date_format 并安装 pm2-logrotate 模块:

pm2 install pm2-logrotate pm2 set pm2-logrotate:max_size 50M pm2 set pm2-logrotate:retain 7

同时建议将错误日志与标准日志分离,通过 error_file 和 out_file 分别指定目录,这样排查问题时目标清晰,也符合云安全审计要求。

pm2如何配置才能持久运行,pm2配置教程 第1张

优雅重启与零停机发布

直接执行 pm2 reload 只能让进程平滑切换,但如果代码需要一次性释放数据库连接等资源,则必须等待旧进程处理完当前请求。

关键配置是 kill_timeout 和 listen_timeout:

  • kill_timeout 给当前进程留出 5 秒完成收尾。
  • listen_timeout 给新进程 8 秒成功监听端口。

更严谨的做法是通过 pm2 deploy 配合 Git Hook 实现自动发布,但这需要额外的部署配置,日常场景下,建议手动执行:

pm2 reload ecosystem.config.js --update-env

而 --update-env 会动态刷新环境变量,避免修改 .env 后必须杀死进程才能生效。

真实案例:西西云服务器上的高可用部署

我曾在西西云一台 2 核 4G 的云主机上部署一个电商 API 网关,访问量峰值约 3000 QPS,初期直接在命令行启动,有一次午夜内存被图片缓存撑爆,PM2 默认策略连续重启进程 16 次,导致负载飙升,SSH 都无法登录。

后来改为 ecosystem 配置后,做了三件事解决问题:

pm2如何配置才能持久运行,pm2配置教程 第2张

  1. 将 instances 固定为 2,避免 max 模式在突发内存压力时频繁 fork 进程。
  2. memory 阈值设为 512M,配合西西云控制台的自定义告警,内存到达 80% 时自动发送短信。
  3. 把 PM2 日志目录挂载到西西云云盘,并设置 7 天自动清理,日志丢失和磁盘占满的问题彻底消失。

这个方案上线后,连续 90 天没有发生过一次宕机,后续使用西西云的 快照回滚 功能做迁移测试,仅用 5 分钟就完整恢复了整个运行环境

容易被忽视的配置细节

环境变量隔离

不要把密钥直接写在 ecosystem.config.js 里,推荐使用:

env_production: { NODE_ENV: 'production', DB_HOST: process.env.DB_HOST }

然后在服务器上使用 pm2 start ecosystem.config.js --env production,密钥通过 shell 环境或西西云 KMS 服务载入,避免源码泄露。

系统级开机自启

pm2 startup 只生成开机自启脚本,真正运行它才能生效:

pm2如何配置才能持久运行,pm2配置教程 第3张

pm2 startup pm2 save

在西西云控制台编辑 crontab 中加入 @reboot pm2 resurrect 是双保险方案,因为云主机会定期做系统维护重启,缺少这一步,配置得再好也会重启后失效。

常见问题排查

症状 排查方向
进程一直在 restart 执行 pm2 logs --err 查看错误栈,检查端口是否被占用
修改配置后不生效 执行 pm2 delete all && pm2 start ecosystem.config.js
集群模式下 Session 丢失 使用 Redis 或数据库存储 Session,避免内存态缓存
日志增长过快 检查 logrotate 配置,以及是否有 console.log 高频触发

相关问答

问:PM2 配置文件中 exec_mode 为 fork 和 cluster 有什么区别?各有什么适用场景?

答:

fork 模式是单进程且无端口复用,适合定时脚本、项目本身维护状态很少的小型服务。cluster 模式会通过端口共享实现多进程负载均衡,适合 HTTP 服务,尤其是 CPU 密集的场景,但注意 cluster 模式要求应用代码是无状态且支持多实例的,如果依赖内存变量做数据同步,socket.io 的 Adapter 没有指向 Redis,那么开多实例反而会引发问题,简单判断:只要是 Web Server,都优先用 cluster;如果是 node-schedule 或 crawler,用 fork 更合适。

问:使用 pm2 reload 与 pm2 restart 对线上服务的影响有何不同?

答:restart 是强制停止进程再重新启动,会造成短暂的服务中断。reload 基于集群模式,自动执行滚动更新先启动新进程,待新进程成功监听端口后再关闭旧进程,整个过程没有请求丢失,但需要注意 reload 依赖 exec_mode: 'cluster' 且应用必须在 listener 回调完成后才认为启动成功,否则 listen_timeout 超时会被判定为启动失败,所以生产发布千万别用 restart 替代 reload,结合前面提到的 kill_timeout 配置,可以做到几乎零感知的发布过程。

写在最后

PM2 配置不是背参数,而是理解每个参数背后的资源边界和故障语义,建议你在自己的测试服务器上,创建一个小型 Express 应用,依次体验 fork 与 cluster 的 CPU 占用差异、max_memory_restart 触发的重启行为、以及 kill_timeout 对在途请求的影响,动手验证一遍,比你背十篇文章都有效。

如果你在生产环境中遇到过更诡异的 PM2 配置问题,欢迎在评论区分享你的踩坑经历,我会挑选典型问题在后续文章中详细拆解。

0