从零搭建个人服务器(04):Node.js 与 PM2
完整记录 Node.js 生产环境部署与 PM2 守护配置:进程守护、集群模式、开机自启与日志管理。
☰ 本文目录(6 节)
服务器跑起来之后,最重要的问题就从「能不能访问」变成了「挂了怎么办」。这一篇记录 Node.js 进程守护与反向代理的完整配置——目标是:重启机器之后,一切自动恢复。
先说结论:不要用 node app.js 直接对外。用 PM2 守护进程、Nginx 反代 80/443、pm2 startup 接管开机自启。
运行时选择#
Node.js 选择 LTS 版本(≥20),通过 NodeSource 源安装,避免 Ubuntu 仓库里的古老版本:
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -sudo apt-get install -y nodejsnode -v # v22.x进程守护#
PM2 的核心价值是:崩溃自动重启、集群模式利用多核、日志管理。最小可用的启动命令:
pm2 start dist/server.js --name blogpm2 save # 保存进程列表pm2 startup systemd # 生成开机自启脚本把「重启后自动恢复」写进部署验收清单——它是最容易被忽略、又最容易在半夜出问题的一环。
配置文件#
项目内维护 ecosystem.config.js,比命令行参数更可追溯:
module.exports = { apps: [{ name: "blog", script: "dist/server.js", instances: 2, exec_mode: "cluster", max_memory_restart: "512M", }],}集群还是单进程#
| 场景 | 建议 | 原因 |
|---|---|---|
| 纯 API / SSR 服务 | cluster × CPU 核数 | 吞吐量线性提升 |
| 内部状态多的服务 | fork 单实例 | 共享内存语义简单 |
| 定时任务进程 | fork 单实例 | 避免重复执行 |
Nginx 反向代理#
Nginx 负责 TLS、压缩与静态资源,Node 只处理动态请求。整体链路如下:
graph LR
U[Visitor] -->|HTTPS :443| N[Nginx]
N -->|proxy_pass :3000| P1[PM2 cluster #1]
N -->|proxy_pass :3000| P2[PM2 cluster #2]
P1 --> D[(日志 / 静态资源)]
P2 --> D关键配置:
server { listen 443 ssl http2; server_name blog.example.com; location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; } location /_next/static/ { alias /var/www/blog/current/.next/static/; expires max; add_header Cache-Control "public, immutable"; }}内存与连接的量化关系可以用一个粗略模型估算——假设单连接平均占用内存服从
Mtotal=n⋅c⋅mˉM_{total} = n \cdot c \cdot \bar{m}Mtotal=n⋅c⋅mˉ
其中 nnn 为集群实例数、ccc 为并发连接、mˉ\bar{m}mˉ 为单连接平均内存,MtotalM_{total}Mtotal 不应超过实例内存预算的 70%。1
上线检查清单#
-
pm2 list状态全部 online,重启次数为 0 -
pm2 startup已执行,服务器重启后自动拉起 - Nginx
-t通过且已 reload - HTTPS 评级达标(目标 A+)
- 日志切割与磁盘告警就位
Footnotes#
-
这是容量规划的粗估模型,实际压测才是金标准:用
autocannon -c 100 -d 30打一轮再下结论。 ↩