Cluster 多进程
VextJS 内置 Cluster 多进程管理,通过 ClusterMaster 管理多个 Worker 进程,充分利用多核 CPU,并支持零停机滚动重启、心跳检测、自动故障恢复等企业级特性。
快速开始
通过配置启用
// src/config/default.ts
export default {
port: 3000,
cluster: {
enabled: true,
workers: 'auto', // 自动检测 CPU 核数
},
};
通过环境变量启用
无需修改配置文件,设置 VEXT_CLUSTER=1 即可开启 Cluster 模式:
VEXT_CLUSTER=1 vext start
启动效果
$ vext start
[vextjs] Cluster master started (PID: 12345)
[vextjs] Spawning 4 workers...
[vextjs] Worker 1 (PID: 12346) ready
[vextjs] Worker 2 (PID: 12347) ready
[vextjs] Worker 3 (PID: 12348) ready
[vextjs] Worker 4 (PID: 12349) ready
[vextjs] All 4 workers ready, listening on port 3000
架构概览
┌──────────────────┐
│ Master Process │
│ (ClusterMaster) │
└────────┬─────────┘
│
┌──────────────┼──────────────┐
│ │ │
┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐
│ Worker 1 │ │ Worker 2 │ │ Worker 3 │
│ (HTTP App) │ │ (HTTP App) │ │ (HTTP App) │
└───────────┘ └───────────┘ └───────────┘
- Master 进程:不处理 HTTP 请求,负责管理 Worker 进程的生命周期
- Worker 进程:每个 Worker 运行一个完整的 VextJS 应用实例,独立处理 HTTP 请求
- IPC 通信:Master 和 Worker 之间通过 Node.js 内置的进程间通信(IPC)交换消息
配置选项
在 config/default.ts 中配置 Cluster 相关选项:
export default {
cluster: {
// 是否启用 Cluster 模式
enabled: true,
// Worker 数量
// 'auto' — 等于 CPU 核数
// 'max' — 等于 CPU 核数
// 'half' — 等于 CPU 核数的一半
// number — 固定数量
workers: 'auto',
// Worker 崩溃时自动重启
autoRestart: true,
// 时间窗口内最大重启次数(超过则停止重启,防止无限崩溃循环)
maxRestarts: 10,
// 重启计数窗口(毫秒)
restartWindow: 60000,
// 重启基础延迟(毫秒,指数退避)
restartBaseDelay: 1000,
// 重启最大延迟(毫秒)
restartMaxDelay: 30000,
// 是否启用 Worker 心跳检测
healthCheck: true,
// 是否允许滚动重启(vext reload 命令)
reload: true,
// PID 文件路径(用于 vext stop / vext reload 定位进程)
pidFile: '.vext.pid',
// Worker 进程标题前缀
titlePrefix: 'vext',
// 是否启用 sticky session(基于客户端 IP 分配固定 Worker)
sticky: false,
},
};
Worker 数量策略
// 生产环境:充分利用所有 CPU 核心
cluster: { workers: 'auto' }
// 共享服务器:只用一半核心
cluster: { workers: 'half' }
// 开发测试:固定 2 个 Worker
cluster: { workers: 2 }
CLI 命令
VextJS CLI 提供了完整的 Cluster 管理命令:
vext start — 启动
# 普通模式启动
vext start
# Cluster 模式启动(通过环境变量)
VEXT_CLUSTER=1 vext start
# 指定端口
vext start --port 8080
如果配置中 cluster.enabled: true 或设置了 VEXT_CLUSTER=1,vext start 会自动以 Cluster 模式启动。
vext stop — 停止
# 停止正在运行的 Cluster
vext stop
vext stop 通过读取 PID 文件(默认 .vext.pid)找到 Master 进程,发送 SIGTERM 信号触发优雅关闭。
关闭流程:
- Master 收到
SIGTERM
- Master 向所有 Worker 发送关闭指令
- 每个 Worker 执行
onClose 钩子(关闭数据库连接等)
- Worker 停止接受新请求,等待现有请求完成
- 超时后强制退出(由
shutdown.timeout 控制)
- 所有 Worker 退出后,Master 退出
- PID 文件自动删除
vext reload — 滚动重启
vext reload 执行零停机滚动重启(Rolling Restart):
- Master 收到 reload 信号
- 逐个重启 Worker(而非一次性全部重启)
- 新 Worker 启动并就绪后,再关闭旧 Worker
- 依次处理所有 Worker
- 整个过程中始终有 Worker 在服务请求
Worker 1: [运行中] → [关闭] → [重启] → [就绪] ✅
Worker 2: [运行中] → [关闭] → [重启] → [就绪] ✅
Worker 3: [运行中] → [关闭] → [重启] → [就绪] ✅
适用场景:
- 部署新版本代码后,无需停机即可让新代码生效
- 更新配置后重载
- 热修复
前提条件
vext reload 要求配置中 cluster.reload: true(默认开启)。如果设置为 false,reload 命令将被拒绝。
vext status — 查看状态
# 查看 Cluster 运行状态
vext status
输出示例:
Cluster Status
──────────────────────────────
Master PID: 12345
Workers: 4 / 4 (all healthy)
Uptime: 2h 35m 12s
Worker PID Status Uptime Requests
1 12346 healthy 2h 35m 12s 45,230
2 12347 healthy 2h 35m 11s 44,891
3 12348 healthy 2h 35m 10s 45,102
4 12349 healthy 2h 35m 09s 44,975
自动故障恢复
Worker 崩溃重启
当 autoRestart: true(默认)时,Worker 崩溃后 Master 会自动重启:
[vextjs] Worker 3 (PID: 12348) exited unexpectedly (code: 1)
[vextjs] Restarting Worker 3... (restart 1/10 in 60s window)
[vextjs] Worker 3 (PID: 12350) ready
指数退避
连续崩溃时,重启延迟逐步增加(指数退避),避免频繁重启消耗系统资源:
第 1 次重启: 延迟 1s (restartBaseDelay)
第 2 次重启: 延迟 2s
第 3 次重启: 延迟 4s
第 4 次重启: 延迟 8s
...
最大延迟: 30s (restartMaxDelay)
崩溃循环保护
如果在 restartWindow(默认 60 秒)内重启次数达到 maxRestarts(默认 10 次),Master 将停止重启并输出告警:
[vextjs] ⚠️ Worker 3 has restarted 10 times in 60s, stopping auto-restart
[vextjs] Please investigate the root cause before manually restarting
这防止了有 Bug 的代码导致无限崩溃-重启循环。
心跳检测
当 healthCheck: true(默认)时,Master 定期向 Worker 发送心跳探测。如果 Worker 长时间未响应(可能死锁或阻塞),Master 会强制杀死并重启该 Worker:
[vextjs] Worker 2 (PID: 12347) heartbeat timeout, killing...
[vextjs] Worker 2 (PID: 12347) force killed
[vextjs] Restarting Worker 2...
[vextjs] Worker 2 (PID: 12351) ready
PID 文件
Cluster 模式启动时,Master 进程会写入 PID 文件(默认 .vext.pid),用于 vext stop / vext reload / vext status 命令定位进程。
PID 文件在以下时机自动管理:
- 创建:Master 启动时
- 删除:Master 正常退出时
- 检测:启动时检测是否已有运行中的 Cluster
# 自定义 PID 文件路径
cluster: { pidFile: '/var/run/myapp.pid' }
Tip
将 .vext.pid 添加到 .gitignore,避免提交到版本控制。
与优雅关闭的配合
Cluster 模式下的优雅关闭流程:
SIGTERM/SIGINT
↓
Master 收到信号
↓
Master 向所有 Worker 发送 shutdown 消息
↓
每个 Worker:
1. 停止接受新连接
2. 等待处理中的请求完成
3. 执行所有 onClose 钩子(LIFO 顺序)
- 关闭数据库连接
- 刷新日志缓冲
- 清理临时资源
4. Worker 退出
↓
所有 Worker 退出后,Master 退出
PID 文件自动删除
超时控制:
- Worker 级超时由
shutdown.timeout(默认 10 秒)控制
- 超时后 Worker 被强制终止(
SIGKILL)
export default {
shutdown: {
timeout: 15000, // 15 秒超时
},
cluster: {
enabled: true,
workers: 'auto',
},
};
按环境配置
// src/config/default.ts — 默认不启用 Cluster
export default {
port: 3000,
// cluster 不配置,默认禁用
};
// src/config/production.ts — 生产环境启用
export default {
cluster: {
enabled: true,
workers: 'auto',
autoRestart: true,
healthCheck: true,
reload: true,
},
};
// src/config/development.ts — 开发环境显式禁用
export default {
cluster: {
enabled: false,
// 开发模式使用 vext dev(热重载),不需要 Cluster
},
};
Tip
开发环境推荐使用 vext dev(热重载模式)而非 Cluster 模式。Cluster 主要用于生产环境的多核利用和高可用。
进程间通信
Master 和 Worker 之间通过 IPC 消息通信。VextJS 定义了标准化的消息协议:
Worker → Master 消息
Master → Worker 消息
与 Docker 部署
在 Docker 容器中使用 Cluster 模式时的注意事项:
Dockerfile 示例
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY dist/ ./dist/
# 使用 SIGTERM 信号(Docker 默认)
STOPSIGNAL SIGTERM
# 启动 Cluster 模式
ENV VEXT_CLUSTER=1
CMD ["node", "dist/lib/bootstrap.js"]
建议
- Worker 数量:Docker 容器中建议根据分配的 CPU 资源设置
workers,而非使用 'auto'('auto' 会检测宿主机的全部 CPU 核心数)
- PID 文件:容器中 PID 文件路径无需特别配置,使用默认的
.vext.pid 即可
- 优雅关闭:确保 Docker 的
stop_grace_period 大于 VextJS 的 shutdown.timeout
- 单容器多进程:Cluster 模式在单容器中运行多个 Worker 是合理的做法,但如果使用 Kubernetes 等编排工具,也可以选择单进程模式 + 多 Pod 副本
# docker-compose.yml
services:
api:
build: .
environment:
- VEXT_CLUSTER=1
- NODE_ENV=production
ports:
- "3000:3000"
stop_grace_period: 30s # 大于 shutdown.timeout
常见问题
Cluster 模式下 WebSocket / SSE 需要注意什么?
长连接(WebSocket、SSE)在 Cluster 模式下需要考虑 sticky session,确保同一客户端的连接始终路由到同一个 Worker。可以通过 cluster.sticky: true 启用。
Worker 数量设多少合适?
- CPU 密集型:设置为 CPU 核数(
'auto')
- I/O 密集型:可以设置为 CPU 核数的 1-2 倍
- 混合负载:从 CPU 核数开始,根据实际监控数据调整
如何监控各 Worker 的状态?
使用 vext status 命令查看各 Worker 的运行状态、PID、存活时间和请求计数。在生产环境中,建议配合 Prometheus 或其他监控工具收集更详细的指标。
与 PM2 有何区别?
VextJS 内置的 Cluster 管理针对框架特性深度集成(如与 onClose 钩子、配置系统、热重载的协作),提供了零配置的开箱即用体验。PM2 是一个通用的进程管理器,功能更广泛但与框架的集成度不如内置方案。两者可以配合使用(PM2 管理 Master 进程),但通常不需要。
下一步
- 了解 CLI 命令 中 Cluster 相关的命令详解
- 查看 配置 中 Cluster 的完整配置项
- 学习 热重载 与 Cluster 的关系
- 探索 测试 中 Cluster 相关的测试方法