保姆级教程:让你的 Node.js 应用永远在线的神器——PM2

保姆级教程:让你的 Node.js 应用永远在线的神器——PM2 保姆级教程让你的 Node.js 应用永远在线的神器——PM2你是否遇到过这样的崩溃瞬间半夜服务器上运行的应用突然挂了用户疯狂投诉而你睡眼惺忪地登录重启又或者每次更新代码都要手动node app.js一关终端就 Game Over今天介绍的这位“瑞士军刀”能让你从此告别这些烦恼。引言想象你有一位 24 小时不睡觉的管家假设你的 Node.js 应用是一个勤快的服务员但它偶尔会累倒崩溃或者一到点就准时下班终端关闭。你需要的不是一个口头鼓励而是一位铁面无私的管家这位管家会服务员一倒下立刻扶起来自动重启餐厅客人太多立刻多安排几个服务员站岗多进程负载均衡记录每个服务员的一言一行方便追责日志管理在新服务员上岗时保证老服务员先别走客人不会察觉零停机重载在 Node.js 的世界里这位管家就叫PM2 (Process Manager 2)。这是一款生产级的进程管理工具能把你的应用从“手工作坊”升级为“自动化工厂”。本篇文章就用最接地气的方式带你从零掌握 PM2让你的 Node.js 应用稳如老狗。一、PM2 到底是什么用一句大白话说PM2 是一个帮你把 Node.js 应用变成“后台服务”的工具。它让你的应用在后台持续运行不依赖终端窗口崩溃、异常退出后自动复活可以利用多核 CPU 并行处理请求集中管理日志不用再console.log到屏幕上找半天一条命令实现更新代码而不中断服务它由 Keymetrics 团队开发完全免费核心功能支持 Linux、macOS、Windows甚至还能管理 Python、Ruby 等其他脚本。只要你会npm install就能立刻拥有。二、10 分钟快速上手2.1 安装确保你已经安装了 Node.js建议版本 14 以上然后打开终端敲下这行命令npminstallpm2-g这一步会把pm2命令安装到系统全局之后在任何目录都能直接使用。2.2 启动你的第一个应用假设你有一个入口文件app.js哪怕它只是console.log(hello)用 PM2 启动它pm2 start app.js神奇的事情发生了你的应用立刻在后台跑了起来即使你关闭终端它也不会停。PM2 会返回一个像这样的进程列表┌─────┬────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┐ │ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ ├─────┼────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┤ │ 0 │ app │ default │ 1.0.0 │ fork │ 12345 │ 0s │ 0 │ online │ 0% │ 25.0mb │ └─────┴────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┘重点看这几个字段idPM2 给每个应用分配的编号后续操作可以直接用 id 或者名称statusonline表示正常运行↺重启次数如果异常退出这里会增长uptime运行时长2.3 常用管理命令pm2 list# 查看所有应用状态pm2 stop app# 停止应用app 是名称或 idpm2 restart app# 重启应用pm2 delete app# 从 PM2 管理列表移除不再自动重启pm2 logs# 实时查看所有应用的日志pm2 monit# 打开一个终端下的监控面板CPU、内存、实时日志小技巧如果应用名称太长用pm2 list找到 id 后直接pm2 stop 0也一样。三、两种工作模式一个服务员 vs 一队服务员这是很多小白容易困惑的点但也是 PM2 的核心亮点。PM2 启动应用时有两种执行模式模式行为适用场景fork单纯开一个子进程运行你的代码小型应用、有状态服务比如 WebSocket 强绑定、定时任务cluster同时开多个子进程共享同一个端口PM2 自动做负载均衡高并发、需要榨干多核 CPU 性能的无状态 API 服务打个比方fork 模式就是雇佣一个全能服务员客户少时够用但来 100 个客人他就忙不过来了。cluster 模式就是开一家连锁店每个窗口CPU 核心配一个服务员客人按顺序分配到不同窗口所有人的等待时间都变短。在 cluster 模式下PM2 利用 Node.js 自带的cluster模块创建一个主进程master和多个工作进程worker。所有 worker 都监听同一个端口主进程负责把网络连接轮询分配给各个 worker这就是所谓的Round-robin 负载均衡。如何开启 cluster 模式pm2 start app.js-imax-i max表示“有多少个 CPU 核心就开多少个进程”。你也可以指定具体数字比如-i 4。⚠️ 重要警告cluster 模式要求你的应用是无状态的。什么意思如果你的应用把用户 session 或临时数据存在进程内存里那么同一个用户下次请求可能被分配到另一个 worker数据就丢了。解决办法是使用 Redis、数据库等外部存储来存放共享状态。如果你的应用必须依赖内存状态比如某些游戏服务器请老老实实用 fork 模式。四、生产环境必杀技配置文件ecosystem.config.js虽然用命令行启动很方便但真正上生产强烈建议你使用配置文件。它能帮你一次管理多个应用固定各种参数避免遗漏轻松区分开发环境和生产环境的变量在项目根目录创建一个ecosystem.config.js名字可以自定义module.exports{apps:[{name:my-api,// 给应用起个名字script:./server.js,// 入口文件instances:max,// 使用所有 CPU 核心exec_mode:cluster,// 集群模式watch:false,// 生产环境不要开文件监听max_memory_restart:500M,// 内存占用超过 500MB 自动重启env:{NODE_ENV:development,PORT:3000},env_production:{NODE_ENV:production,PORT:80},error_file:./logs/err.log,// 错误日志专门存放out_file:./logs/out.log,// 普通日志存放merge_logs:true,// 集群模式下所有 worker 日志合并log_date_format:YYYY-MM-DD HH:mm:ss Z}]};然后启动时指定环境pm2 start ecosystem.config.js--envproduction配置文件里几个救命参数详解max_memory_restart内存泄漏是 Node.js 应用的常见病这个参数就是你的“自动退烧药”。内存飙到设定值PM2 无脑重启该进程保证服务不会因为内存爆掉而彻底瘫痪。autorestart: true默认开启崩溃自动复活。如果你希望只在特定情况下自动重启可以写false。max_restarts如果应用在短时间内反复崩溃PM2 会认为它“没救了”从而停止重启避免无限循环消耗资源。默认 15 次。min_uptime进程至少要运行多久才被认为是“正常启动”。配合max_restarts使用比如min_uptime: 10s, max_restarts: 5表示如果 10 秒内连续崩溃 5 次就不再重启。五、日志管理再也不怕黑夜里的 bug5.1 日志都去哪了默认情况下PM2 会把每个应用的输出console.log和错误信息保存到~/.pm2/logs/文件夹文件名为应用名-out.log和应用名-error.log。常用命令pm2 logs# 实时滚动所有应用的日志类似 tail -fpm2 logs my-api# 只看 my-api 的日志pm2 logs--lines200# 显示最近 200 行pm2 flush# 一键清空所有日志磁盘告急时特好用5.2 日志切分防止硬盘被撑爆如果不做任何限制日志文件会越来越大最终占满磁盘。PM2 官方提供了模块pm2-logrotate来解决这个问题。安装pm2installpm2-logrotate安装后按需配置都是字面意思pm2setpm2-logrotate:max_size 10M# 单个日志文件超过 10MB 自动切分pm2setpm2-logrotate:retain30# 保留最近 30 个文件老的删掉pm2setpm2-logrotate:compresstrue# 被切分的老日志压缩保存这样你就拥有了一个全自动的日志管家根本不用操心。六、零停机重载用户无感知的代码更新传统更新代码的流程是git pull→ 关闭应用 → 重启这中间至少有几秒到十几秒的服务中断高峰期那就是一场灾难。PM2 的绝招在 cluster 模式下pm2 reload可以做到零停机重载也叫滚动重启。原理解析配合上面的服务员比喻PM2 先悄悄启动一个全新的服务员新版本进程。等新服务员准备就绪PM2 把客人新请求指给新服务员同时告诉老服务员“你可以先不接新客人了把手头的客人服务完”。老服务员处理完手头工作后优雅地退出。重复以上步骤逐个替换所有服务员整个过程客人完全没有感觉到任何停顿。实操就是一句命令pm2 reload my-api或者如果你用配置文件启动直接pm2 reload ecosystem.config.js注意在 fork 模式下reload退化为restart会有短暂中断。而且 reload 对无状态应用效果最好如果你有 WebSocket 长连接reload 时连接会断开除非你做了额外的连接迁移处理。七、开机自启服务器重启后自动复活服务器总是要定期维护重启的你肯定不希望每次重启后都要手动敲pm2 start。设置开机自启动只需三步# 1. 让 PM2 根据你的操作系统生成对应的启动脚本它会自动检测是 systemd、launchd 还是其他pm2 startup# 2. 把当前所有运行的应用保存为一个“复活列表”pm2 save# 3. (可选) 将来某一天想恢复这个列表pm2 resurrect完成之后哪怕是机房断电又来电你的应用也会自动回到工作岗位。八、Docker 环境下的正确打开方式现在微服务、容器化大行其道很多人会把 PM2 塞进 Docker。但要注意容器本身就是一个进程管理器比如 Kubernetes 管理 Pod双重管理容易出问题。如果非要用请遵守这个准则用pm2-runtime代替pm2作为容器入口命令。它会保证 PM2 在前台运行并且能正确将SIGTERM等信号传递给你的应用让容器能优雅退出。示例 Dockerfile 片段FROM node:20-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --production COPY . . RUN npm install pm2 -g EXPOSE 3000 CMD [pm2-runtime, start, ecosystem.config.js]这样既享受了 PM2 的进程守护和负载均衡又不违背容器的设计哲学。九、锦上添花Web 监控面板 PM2 Plus如果你觉得终端下pm2 monit太素了可以试试官方的 Web 版监控服务原来叫 Keymetrics现在叫 PM2 Plus。它能在网页上实时查看所有服务器的 CPU、内存、事件循环延迟集中管理多台机器设置告警CPU 过高给你发 Slack、邮件连接方式简单pm2linksecret_keypublic_key注册地址https://pm2.io/免费版有小限制个人项目或小团队够用了。十、总结你的应用终于有了“守护神”学完这套保姆级教程你应该能够✅ 理解 PM2 是干什么的以及它为什么能提升应用稳定性✅ 使用 fork 和 cluster 模式应对不同场景✅ 编写ecosystem.config.js规范化管理生产环境✅ 轻松搞定日志、自启、零停机部署✅ 知道在 Docker 中该如何正确使用 PM2PM2 不是银弹对于大型分布式系统你可能还需要 Kubernetes 这样的编排工具。但对于 90% 的 Node.js 项目来说PM2 能以极低的成本带来极高的可靠性提升堪称个人开发者和小团队的“运维救星”。下次当你看到 PM2 列表里那个绿油油的online状态时心中默念今晚终于可以睡个安稳觉了。