华为云 ECS 实战:基于 Node.js 与 PM2 构建多核高可用服务集群、日志轮转及零停机发布
前言
在现代全栈开发与前端工程化体系中,Node.js 凭借非阻塞 I/O 与事件驱动架构,被广泛应用于构建 SSR(服务端渲染)应用、BFF(服务于前端的后端)中间层以及高并发实时 API 服务。然而,由于 JavaScript 语言本身是单线程运行的,如果直接在华为云弹性云服务器(ECS)上使用 node app.js 启动应用,即使服务器拥有 2 核、4 核甚至更多 CPU 核心,Node.js 进程也只能利用其中 1 个核心的算力,且一旦遇到未捕获异常,整个服务便会直接崩溃退出。
本文将完整演示在华为云 Ubuntu 22.04 LTS 实例上,利用生产级进程管理器 PM2 开启 Cluster(多核集群)模式、配置 自动化日志切割(Log Rotate) 以及绑定 Systemd 开机自启守护 的全套实战流程。
一、 环境准备与 Node.js LTS 安装
为了确保生产环境的长期稳定性,我们推荐使用 NodeSource 官方源或 NVM 安装最新的 Node.js LTS(长期支持版)。
1. 配置软件源并安装 Node.js 20 LTS
通过 SSH 登录华为云 ECS 终端,执行以下命令安装基础依赖与 Node.js:
sudo apt update && sudo apt install -y curl git build-essential nginx
# 导入 NodeSource 20.x LTS 官方仓库并安装
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
# 验证 Node.js 与 npm 版本
node -v
npm -v
2. 配置华为云 npm 镜像加速并安装 PM2
为了提升国内云服务器下载 npm 依赖包的速度,我们将镜像源切换为华为云开源镜像站,并全局安装 pm2:
# 配置华为云 npm 镜像加速源
npm config set registry https://mirrors.huaweicloud.com/repository/npm/
# 全局安装 PM2 进程管理器
sudo npm install -g pm2
# 验证安装结果
pm2 -v
二、 编写示例应用与 PM2 集群编排文件
1. 创建 Node.js 后端服务代码
我们在 /opt/node_app 目录下创建一个轻量级 HTTP 服务 /opt/node_app/app.js,用于在响应中返回当前处理请求的进程 PID 与内存占用情况:
sudo mkdir -p /opt/node_app/logs
sudo chown -R $USER:$USER /opt/node_app
cd /opt/node_app
cat << 'EOF' > /opt/node_app/app.js
const http = require('http');
const os = require('os');
const PORT = process.env.PORT || 3000;
const server = http.createServer((req, res) => {
if (req.url === '/health') {
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
res.end(JSON.stringify({
status: 'UP',
worker_pid: process.pid,
hostname: os.hostname(),
memory_rss_mb: Math.round(process.memoryUsage().rss / 1024 / 1024),
uptime_sec: Math.round(process.uptime())
}));
return;
}
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end(`Hello from HuaweiCloud ECS! Handled by Worker PID: ${process.pid}\n`);
});
server.listen(PORT, '127.0.0.1', () => {
console.log(`[Worker ${process.pid}] Server is running at http://127.0.0.1:${PORT}`);
});
EOF
2. 编写 ecosystem.config.js 生产配置文件
相比在命令行拼接复杂的启动参数,使用 PM2 的 ecosystem.config.js 配置文件可以更清晰地管理环境变量、集群实例数以及内存防泄漏重启阈值:
cat << 'EOF' > /opt/node_app/ecosystem.config.js
module.exports = {
apps: [
{
name: 'huaweicloud-node-api',
script: './app.js',
cwd: '/opt/node_app',
// 开启集群模式,自动根据华为云 ECS 的 CPU 核心数启动对应数量的进程
instances: 'max',
exec_mode: 'cluster',
// 当单个进程物理内存占用超过 500M 时自动平滑重启,防止内存泄漏引发 OOM
max_memory_restart: '500M',
// 日志时间戳与输出路径配置
time: true,
out_file: '/opt/node_app/logs/app-out.log',
error_file: '/opt/node_app/logs/app-error.log',
merge_logs: true,
// 生产环境变量
env_production: {
NODE_ENV: 'production',
PORT: 3000
}
}
]
};
EOF
三、 启动多核集群与配置零停机热重载
1. 启动集群并查看负载状态
使用 --env production 参数加载生产配置启动服务:
cd /opt/node_app
pm2 start ecosystem.config.js --env production
# 查看进程集群列表
pm2 list
此时在终端输出的表格中,可以看到 mode 列显示为 cluster,且实例数量与当前华为云 ECS 的 vCPU 核心数完全一致。我们可以连续发起请求验证多进程负载均衡效果:
curl -s http://127.0.0.1:3000/health
curl -s http://127.0.0.1:3000/health
观察返回的 worker_pid 数值,可以看到请求被均匀分发到了不同的 Node.js 工作进程上。
2. 零停机平滑发布(Graceful Reload)
当业务代码发生更新需要上线时,切勿使用 pm2 restart(会同时中断所有进程导致短暂报错)。应当使用 reload 命令,让 PM2 逐个替换旧工作进程,确保任何时刻都有活跃进程处理用户请求:
pm2 reload huaweicloud-node-api
四、 配置 PM2 日志自动切割与开机自启
1. 安装 pm2-logrotate 防止日志撑爆云硬盘
PM2 默认会持续将标准输出与错误日志追加到文件中。为了防止长期运行占满华为云 ECS 系统盘,我们需要安装并配置官方的日志切割模块:
# 安装日志轮转插件
pm2 install pm2-logrotate
# 设置单个日志文件最大体积为 50MB
pm2 set pm2-logrotate:max_size 50M
# 最多保留最近 14 个归档日志文件
pm2 set pm2-logrotate:retain 14
# 开启 gzip 压缩归档日志
pm2 set pm2-logrotate:compress true
2. 配置 Systemd 开机自动恢复进程列表
为了让华为云 ECS 在系统重启后能够自动拉起 PM2 及其托管的所有 Node.js 进程,执行以下固化命令:
# 1. 保存当前正在运行的 PM2 进程列表快照
pm2 save
# 2. 生成并配置 Systemd 开机自启服务
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u $USER --hp $HOME
五、 配置宿主机 Nginx 反向代理
最后,我们在宿主机配置 Nginx,将公网 80 端口流量转发至本地回环端口 127.0.0.1:3000:
sudo tee /etc/nginx/conf.d/node_app.conf << 'EOF'
server {
listen 80;
server_name _;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache_bypass $http_upgrade;
}
}
EOF
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx
总结
通过 “PM2 Cluster 多核集群调度 + 内存阈值自动重启 + pm2-logrotate 日志自动轮转压缩 + Systemd 开机自启” 的组合方案,我们彻底解决了 Node.js 单线程模型在多核云服务器上的算力浪费与单点脆弱问题。配合宿主机 Nginx 的反向代理,即可在华为云 ECS 上轻松构建出高并发、零停机发布的现代全栈服务架构。
- 点赞
- 收藏
- 关注作者
评论(0)