┌─────────────────────────────┐
│ 🌐 客户端层 │
│─────────────────────────────│
│ 用户浏览器、App、API 调用方 │
│ - 发送HTTP请求至LB入口 │
│ - 显示最终响应内容 │
└─────────────────────────────┘
│
▼
┌───────────────────────────────────────────┐
│ 🧠 Node.js 负载均衡层 (LB) │
│───────────────────────────────────────────│
│ [1] 请求接入模块 │
│ • 监听外部端口(3000) │
│ • 接收来自客户端的请求 │
│ │
│ [2] 负载调度模块 │
│ • 调度策略:轮询 / 最少连接数 │
│ • 分配目标 Worker 实例 │
│ │
│ [3] 健康检查模块 (Health Checker) │
│ • 定期 ping 后端实例健康状态 │
│ • 失败后暂时移出任务分发队列 │
│ │
│ [4] 动态扩缩容模块 (AutoScaler) │
│ • 监控每秒请求量 / 平均响应时间 │
│ • 若超阈值 → spawn 新 Worker │
│ • 若空闲 → kill 闲置 Worker │
│ │
│ [5] 异常处理与日志模块 │
│ • 捕获 worker 错误 │
│ • 输出负载、健康、扩容日志 │
└───────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ ⚙️ Node.js Worker 实例池 (后端层) │
│─────────────────────────────────────────────│
│ 每个实例独立运行 server.js,监听不同端口: │
│ │
│ ┌──────────┐ ┌──────────┐ ┌────────────┐ │
│ │ Worker 1 │ │ Worker 2 │ │ Worker 3 │ │
│ │ Port:4001│ │ Port:4002│ │ Port:4003 │ │
│ │ 状态:✅ │ │ 状态:✅ │ │ 状态:❌(下线)│ │
│ └──────────┘ └──────────┘ └────────────┘ │
│ │
│ - Worker 接收分配任务 │
│ - 执行计算 / IO / 数据处理 │
│ - 返回结果至 LB │
│ - 支持不同类型的任务脚本路径 │
│ (如 ./workers/tasks/square_sum.js) │
└─────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────┐
│ 📊 监控与日志层 (可选) │
│───────────────────────────────────────────│
│ • 接收 LB 输出的 metrics 数据 │
│ • 展示系统负载、响应时间、Worker状态 │
│ • 可对接 Prometheus + Grafana │
│ • 支持报警通知 │
└───────────────────────────────────────────┘- 轮询调度
- 健康检查
- 动态扩缩容
- 任务分发
- Prometheus 兼容监控接口
Frontend → LB (API Router) → Server Worker → Task 前提:
- 安装mysql并启动,初始化脚本:db/mysql.sql(必选)
- 初始化
# 1) 生成/更新 client npx prisma generate # 2) 如果需要把 schema 改写入数据库(开发环境) npx prisma migrate dev --name fix-logs-relation
- 安装redis并启动(必选)
- 安装prometheus并配置启动(可选)
- 安装grafana并配置启动(可选)
cd 项目目录\安装依赖:
npm install启动:
node lb.jsDB Worker:
curl -X POST http://localhost:3100/api/users -H "Content-Type: application/json" -d "{\"userName\":\"xqy77\",\"passWord\":\"123\"}"
curl -X GET http://localhost:3100/api/users/1Compute Worker:
curl -X POST http://localhost:3100/api/compute -H "Content-Type: application/json" -d '{"type":"squreSum","payload":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]}'
curl -X POST http://localhost:3100/api/compute -H "Content-Type: application/json" -d '{"type":"squreSum","payload":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100]}'查看监控指标:
curl http://localhost:3100/metricsCache Worker: 缓存写入:
curl -X POST http://localhost:4000/task \
-H "Content-Type: application/json" \
-d '{"op":"set","key":"user:1","value":{"name":"xqy111"},"ttl":10}'读取缓存:
curl -X POST http://localhost:4000/task \
-H "Content-Type: application/json" \
-d '{"op":"get","key":"user:1"}'删除缓存:
curl -X POST http://localhost:4000/task \
-H "Content-Type: application/json" \
-d '{"op":"del","key":"user:1"}'| 层级 | 模块 | 暴露端口 | Prometheus job 名称 |
|---|---|---|---|
| LB 层 | lb.js |
:3000/metrics |
job="load_balancer" |
| Worker 层 | db.js, compute.js |
各自端口,如 :4001/metrics |
job="worker" |
| Task 层 | 在 Worker 内部定义 label | 同 Worker | 同上,通过 type 区分任务 |
prometheus.yml
scrape_configs:
- job_name: 'load_balancer'
static_configs:
- targets: ['localhost:3100']
- job_name: 'worker'
static_configs:
- targets: ['localhost:4000', 'localhost:4001', 'localhost:4002', 'localhost:4003', 'localhost:4004'] ┌────────────────────────────┐
│ Grafana Dashboard │
│ (Task latency / Success %) │
└──────────────┬─────────────┘
│
Prometheus Pulls
│
┌───────────────────┼───────────────────┐
│ │ │
┌───────────────┐ ┌───────────────┐ ┌─────────────────┐
│ LB /metrics │ │ Worker 1 │ │ Worker 2 │
│ (task routing)│ │ db.js /metrics│ │ image.js/metrics│
└─────┬─────────┘ └───────────────┘ └─────────────────┘
│
│ distributes tasks via round-robin
│
┌───────────────────────────────┐
│ Task Pool │
│ (db_query, image_process...) │
└───────────────────────────────┘
说明:
| 功能 | 实现方式 | 监控粒度 |
|---|---|---|
| 仅看系统负载 | LB 层 metrics | 全局 |
| 看实例运行状况 | Worker 层 metrics | 实例级 |
| 精确到任务性能 | Task label metrics | 任务级 |
| 分析延迟瓶颈 | Histogram + Grafana | 时延/P95/P99 |
node stress.js| 对比项 | Node.js 负载均衡(应用层LB) | Nginx 负载均衡(反向代理层LB) |
|---|---|---|
| 层级位置 | 应用层(L7,HTTP/逻辑层) | 网络层/L7(主用于HTTP/TCP代理) |
| 主要用途 | 在 Node.js 内部分配业务逻辑或任务计算 | 转发请求到多个后端服务 |
| 负载策略 | 可自定义(轮询、最少连接、自定义算法) | 预置策略(轮询、IP hash、least_conn等) |
| 健康检查 | 可自定义逻辑(调用 /health、Redis 检测等) | 基于 upstream 机制的简单健康检测 |
| 扩缩容 | 可动态 spawn/kil 子进程(AutoScaler) | 通常需人工或外部工具更新配置 |
| 动态注册 | 可支持 worker 动态注册/下线 | 一般需 reload 配置文件 |
| 状态感知 | 可结合 Redis/DB 实现状态路由(例如按用户、任务类型) | 无法感知业务状态,仅转发流量 |
| 性能 | 单实例性能低于 Nginx(因为 JS 层转发) | 高性能、C 实现、事件驱动 |
| 灵活性 | 逻辑层路由极强,可做智能任务调度 | 功能稳定、通用代理 |
| 典型场景 | 微服务调度、任务派发、应用内水平扩展 | 静态资源代理、API 网关、前端反向代理 |