1. 初识PM2:你的Node.js应用“贴身管家”
如果你写过Node.js应用,尤其是部署到服务器上,肯定遇到过这个头疼的问题:我关掉终端窗口,或者SSH连接一断,我的Node服务怎么就跟着挂了?这感觉就像你养了只电子宠物,必须24小时盯着屏幕,一离开就“饿死”了。在早期,我们可能会用nohup或者screen这类系统工具来让进程在后台存活,但用起来总有点别扭,管理起来也不方便,更别提什么自动重启、性能监控了。
PM2就是来解决这些“糟心事”的。你可以把它想象成你Node.js应用的“贴身管家”或者“超级保姆”。它不只是一个简单的后台启动工具,而是一个功能完整的进程管理器。我用了这么多年,感觉最深的一点是,它把很多生产环境里必须做但又很繁琐的事情,用一条简单的命令就搞定了。比如,你的应用因为一个未捕获的异常崩溃了,传统方式你得手动登录服务器去重启。有了PM2,它能在毫秒级内自动帮你把应用重新拉起来,保证服务的高可用性。再比如,你想看看应用运行得好不好,CPU和内存吃了多少,不用再去翻一堆复杂的系统监控命令,PM2内置的监控面板一目了然。
更重要的是,PM2特别适合生产环境。很多新手朋友容易把开发环境和生产环境的管理混为一谈。在本地开发时,我们习惯用node app.js直接跑,改了代码手动重启。但到了线上,这套就行不通了。PM2提供的集群模式,能一键启动多个应用实例,充分利用服务器的多核CPU性能,实现负载均衡。还有零停机重启,这在需要更新应用版本时简直是神器,能做到用户无感知的平滑更新。所以,无论你是个人项目的小打小闹,还是企业级应用的严肃部署,花点时间掌握PM2,绝对是笔稳赚不赔的投资。
2. 从安装到上手:你的第一个PM2应用
2.1 安装PM2:一行命令的事
安装PM2简单得超乎想象,因为它是一个Node.js模块。打开你的终端(Windows用CMD或PowerShell,Mac/Linux用Terminal),输入下面这条命令:
npm install pm2 -g
那个 -g 参数代表全局安装,这样你才能在系统的任何地方直接使用 pm2 命令。安装完成后,别忘了验证一下,输入:
pm2 --version
如果终端里蹦出了一个版本号,比如 5.3.0,那就恭喜你,安装成功了。这里我踩过一个小坑,有时候在Linux或Mac上会因为权限问题安装失败,系统会提示你权限不够。别慌,有两种解决方法:一是加上sudo前缀,用管理员权限安装(sudo npm install pm2 -g);二是在命令后面加上 --unsafe-perm 参数来绕过权限检查。我个人更推荐第一种,毕竟更规范。
2.2 启动应用:基础与进阶玩法
安装好了,我们来启动一个最简单的Node.js应用。假设你的入口文件叫 server.js,那么进入项目目录,直接运行:
pm2 start server.js
就这么简单,你的应用已经在后台默默运行起来了。关掉终端试试?应用依然坚挺。这时候你运行 pm2 list,就能看到一个所有由PM2管理的应用列表,里面会有你刚启动的 server 应用(PM2默认会去掉.js后缀作为应用名)。
但直接这样用有点“裸奔”,我建议你从一开始就养成好习惯,使用 --name 参数给你的应用起个响亮的名字:
pm2 start server.js --name "我的API服务"
这样在列表里清晰明了,管理起来也方便。接下来是两个生产环境必用的高级启动选项。
第一个是集群模式。现在的服务器CPU都是多核的,但Node.js默认是单进程的,只能用到其中一个核,这不是浪费吗?PM2的集群模式可以一键启动多个应用实例,均衡地跑在每个CPU核心上。命令很简单:
pm2 start server.js -i max
这个 -i max 会让PM2自动检测你的CPU核心数,并启动对应数量的实例。比如你的服务器是4核的,它就会启动4个 server.js 进程。PM2会在内部做一个负载均衡,把进来的网络请求分发给这些进程,极大地提升了应用的吞吐量和并发能力。这是提升Node.js应用性能最直接、最有效的手段之一。
第二个是监听文件变化,这主要用在开发阶段,非常方便:
pm2 start server.js --watch
加上 --watch 参数后,PM2会监控你项目目录下的文件。一旦你修改并保存了任何文件,PM2会自动重启应用,让你立刻看到修改效果,省去了手动停止再启动的麻烦。
3. 日常运维核心:查看、停止与重启
3.1 查看应用状态:一切尽在掌握
应用启动后,你不能当“甩手掌柜”。PM2提供了强大的状态查看功能。最常用的就是 pm2 list(或者简写 pm2 ls)。这个命令会输出一个漂亮的表格,我把它包含的信息拆解一下:
- id: 进程的内部ID,一个数字,用于快速操作。
- name: 你给应用起的名字,或者PM2自动生成的名字。
- mode: 运行模式,
fork是单实例,cluster是集群模式。 - pid: 操作系统分配给这个进程的真实ID。
- uptime: 应用已经运行了多久,比如
2D代表2天,3h代表3小时。 - memory: 当前占用的内存大小。
- cpu: 当前占用的CPU百分比。
这个列表让你对所有“手下”的运行概况一目了然。如果你想深入了解某一个“兵”,比如想看它的运行路径、启动参数、环境变量等详细信息,就用:
pm2 show 我的API服务
# 或者用 id
pm2 show 0
3.2 停止应用:优雅地按下暂停键
当需要停止应用时,比如你要部署新代码,正确的停止顺序很重要。停止单个应用:
pm2 stop 我的API服务
# 或者
pm2 stop 0
执行后,这个应用的状态在 pm2 list 里会变成 stopped。它并没有被删除,只是暂停了,你可以随时用 pm2 start 我的API服务 把它重新拉起来。
如果你需要停下所有由PM2管理的应用,一条命令搞定:
pm2 stop all
有时候,某个应用你可能彻底不需要了,想把它从PM2的管理列表中清除,这时要用 delete 命令:
pm2 delete 我的API服务
这个操作会先停止应用,然后将其从列表中移除。pm2 list 里就看不到它了。
3.3 重启应用:两种策略应对不同场景
重启是运维高频操作,PM2提供了两种方式,对应不同场景。
第一种是普通重启 restart:
pm2 restart 我的API服务
这个过程是:先停止旧进程,然后立刻启动新进程。中间会有一个非常短暂的服务中断间隙。在开发环境或者对短暂中断不敏感的场景下,用这个没问题。
第二种是零停机重启(优雅重载) reload,这是生产环境的推荐做法:
pm2 reload 我的API服务
这个命令的机制就高级了。对于集群模式运行的应用,PM2会逐个重启每一个工作进程。它会先启动一个新的工作进程,等这个新进程完全就绪、可以接受请求后,再优雅地关闭一个旧进程。如此循环,直到所有旧进程都被替换成新进程。在整个过程中,始终有工作进程在对外服务,从而实现了用户无感知的平滑更新。如果你的应用是有状态的(比如用户WebSocket连接),一定要在代码里处理好 SIGINT 或 SIGTERM 信号,实现优雅关闭,避免连接突然断掉。
4. 洞察与诊断:日志与性能监控实战
4.1 日志管理:问题追踪的生命线
日志是排查线上问题的“黑匣子”,PM2帮你管得明明白白。默认情况下,PM2会把应用的标准输出(stdout)和错误输出(stderr)分别保存到日志文件中,通常在你的 ~/.pm2/logs/ 目录下。
最直接的看日志方式,是使用 logs 命令:
pm2 logs 我的API服务
这会以实时流的方式,在终端里打印出该应用的最新日志,并且会持续刷新。当你正在调试或者观察应用启动过程时,这个功能非常有用。按 Ctrl+C 可以退出实时查看模式。
如果你只是想快速看一眼最近出了什么错,可以指定行数:
pm2 logs 我的API服务 --lines 200
这只会打印出最新的200行日志,不会持续跟踪。时间长了,日志文件会变得很大,PM2也提供了清空所有日志的命令:
pm2 flush
这个命令会清空 ~/.pm2/logs/ 目录下所有日志文件的内容,但文件本身还在。我建议在每次重大版本更新前执行一次,方便区分新旧日志。
4.2 性能监控:让瓶颈无处可藏
除了管理进程,PM2还是一个轻量级的性能监控工具。想知道你的应用吃了多少内存,CPU占用高不高?不用安装额外的监控系统,PM2自带一个交互式监控面板:
pm2 monit
运行后,你会看到一个分屏的终端界面。上半部分类似 pm2 list 的表格,实时刷新着每个进程的CPU和内存占用率。下半部分则是一个更直观的进程列表和系统资源概览。哪个进程突然内存泄漏,CPU飙高,在这里一眼就能发现。对于快速诊断性能问题,这个工具足够了。
当你需要更深入的分析,或者想生成一个报告给其他人看时,可以用:
pm2 report
这个命令会生成一个包含大量诊断信息的报告,包括PM2版本、系统信息、环境变量、各个应用的详细状态等,并提供一个本地的HTTP链接让你在浏览器中查看,非常利于故障排查。
5. 迈向生产环境:高级配置与生态集成
5.1 使用配置文件:告别冗长命令
当你需要管理的应用越来越多,或者启动参数越来越复杂时,还在命令行里写一长串 -- 参数就太不优雅了,也容易出错。PM2推荐使用 ecosystem.config.js 配置文件。在你的项目根目录下创建这个文件:
module.exports = {
apps: [{
name: "我的生产环境API", // 应用名称
script: "./server.js", // 入口脚本路径
instances: "max", // 集群实例数,max表示按CPU核心数
exec_mode: "cluster", // 集群模式
watch: false, // 生产环境关闭监听,否则可能频繁重启
env: {
NODE_ENV: "development", // 默认环境变量
PORT: 3000
},
env_production: {
NODE_ENV: "production", // 生产环境特定变量
PORT: 80
},
max_memory_restart: "1G", // 内存超过1G自动重启,防止内存泄漏
log_date_format: "YYYY-MM-DD HH:mm Z", // 日志时间格式
error_file: "./logs/app-err.log", // 错误日志路径
out_file: "./logs/app-out.log", // 输出日志路径
merge_logs: true, // 集群模式下合并日志
}]
};
有了这个配置文件,启动就变得无比简洁和可重复:
# 使用生产环境变量启动
pm2 start ecosystem.config.js --env production
# 重启
pm2 restart ecosystem.config.js --env production
# 重载
pm2 reload ecosystem.config.js --env production
所有配置集中管理,一目了然,也方便纳入版本控制。
5.2 开机自启动:确保服务永在线
服务器难免会遇到重启,比如系统安全更新或者硬件维护。你肯定不希望每次重启后都要手动登录服务器去启动你的Node.js应用。PM2的 startup 功能就是解决这个问题的。
首先,把你当前PM2管理的应用列表保存一下:
pm2 save
这个命令会把当前运行的应用列表及其配置,持久化到 ~/.pm2/dump.pm2 文件里。
然后,根据你的操作系统,生成并配置开机自启动脚本:
pm2 startup
运行这个命令后,PM2会检测你的系统(是systemd, upstart还是init.d),并在终端里打印出一行需要你以管理员权限执行的命令。比如在Ubuntu使用systemd的系统上,它可能会输出:
[PM2] Init System found: systemd
[PM2] To setup the Startup Script, copy/paste the following command:
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u your_username --hp /home/your_username
你一定要把这条命令复制下来,然后运行它。 这个步骤是很多新手会忽略的,只运行了 pm2 startup 而没有执行它输出的命令,导致开机自启动没有真正生效。
配置好后,下次服务器重启,你的PM2以及它之前保存的应用列表,都会自动恢复运行。如果想取消这个开机自启动,运行 pm2 unstartup 即可。
5.3 内存与异常管控:为应用加上安全阀
在生产环境,我们最怕两件事:内存泄漏和进程僵死。PM2提供了一些参数来设置“安全阀”。
比如 max_memory_restart,我们刚才在配置文件里见过了。它指定一个内存上限(如 512M 或 1G),当PM2监测到某个应用实例的内存占用超过这个阈值时,会自动重启该实例。这虽然不能解决内存泄漏的根本问题,但能防止单个进程吃光所有服务器内存,导致系统崩溃,为你修复Bug争取了时间。
另一个有用的参数是 exp_backoff_restart_delay。想象一下,如果你的应用代码有问题,一启动就崩溃,PM2会立刻重启它,然后又崩溃,又重启……这会形成一个疯狂的重启循环,瞬间产生大量日志,占用CPU。这个参数可以设置一个指数级增长的重启延迟(比如 100 毫秒),让PM2在应用连续启动失败时,等待越来越长的时间再尝试重启,避免雪崩效应。
把这些高级功能用好,你的Node.js应用就真正具备了生产级应用的韧性。从我自己的经验来看,从手动管理到使用PM2,再到熟练运用这些高级特性,是一个Node.js后端开发者运维能力成熟的重要标志。它让你能更专注于业务逻辑开发,而不是整天操心进程怎么又挂了。

1662

被折叠的 条评论
为什么被折叠?



