服务端优化: - Socket.IO 配置优化,支持高并发 WebSocket 连接 - 添加 connectTimeout、perMessageDeflate 等参数 压测脚本: - 新增 vote-real-scenario.yaml 真实场景压测配置 - 支持 100人瞬间爆发、每人7票、不同投票速度模拟 - 添加随机延迟函数模拟真实用户行为 - 强制 WebSocket 传输避免 HTTP 连接限制 前端修复: - 修复 PostcardItem、PostcardDisplay 奖项名称硬编码问题 - 组件现在从后端 awards 配置动态获取奖项名称 - 修复 LiveVotingView、AdminControl 传递 awards 数据 - 新增 gala 压测命令到 package.json 测试验证: - 100人并发压测通过,成功率 100% - P95 延迟 0.7ms,远低于 500ms 阈值 - 系统可稳定支持 3.3 倍现场负载
209 lines
5.8 KiB
YAML
209 lines
5.8 KiB
YAML
# ============================================================================
|
||
# 年会互动大屏系统 - 投票压力测试配置 (100人场景)
|
||
# ============================================================================
|
||
#
|
||
# 运行方式:
|
||
# pnpm test:load # 标准测试 (30并发)
|
||
# pnpm test:load:smoke # 冒烟测试 (5并发, 10秒)
|
||
# pnpm test:load:peak # 峰值测试 (80并发)
|
||
# pnpm test:load:stress # 压力测试 (120并发)
|
||
#
|
||
# ============================================================================
|
||
|
||
config:
|
||
target: "http://127.0.0.1:3000"
|
||
|
||
# 性能阈值
|
||
ensure:
|
||
p95: 500
|
||
maxErrorRate: 1
|
||
|
||
# Socket.IO 配置 - 强制使用 WebSocket 避免高并发下 HTTP 连接限制
|
||
socketio:
|
||
transports: ["websocket"] # 只使用 WebSocket,禁用 polling
|
||
path: "/socket.io"
|
||
extraHeaders:
|
||
Origin: "http://localhost:5174"
|
||
|
||
# 默认 phases (被环境配置覆盖)
|
||
phases:
|
||
- duration: 1
|
||
arrivalRate: 1
|
||
|
||
# 环境变量
|
||
variables:
|
||
programIds:
|
||
- "p1"
|
||
- "p2"
|
||
- "p3"
|
||
- "p4"
|
||
- "p5"
|
||
- "p6"
|
||
- "p7"
|
||
ticketTypes:
|
||
- "creative"
|
||
- "visual"
|
||
- "atmosphere"
|
||
- "performance"
|
||
- "teamwork"
|
||
- "popularity"
|
||
- "potential"
|
||
|
||
# 处理器脚本
|
||
processor: "./vote-processor.cjs"
|
||
|
||
# 环境配置
|
||
environments:
|
||
# 冒烟测试 - 快速验证 (10秒, 5并发)
|
||
smoke:
|
||
target: "http://127.0.0.1:3000"
|
||
phases:
|
||
- name: "冒烟测试"
|
||
duration: 10
|
||
arrivalRate: 5
|
||
|
||
# 标准测试 - 正常负载 (30秒, 30并发)
|
||
standard:
|
||
target: "http://127.0.0.1:3000"
|
||
phases:
|
||
- name: "预热"
|
||
duration: 5
|
||
arrivalRate: 5
|
||
- name: "正常负载"
|
||
duration: 20
|
||
arrivalRate: 30
|
||
- name: "冷却"
|
||
duration: 5
|
||
arrivalRate: 5
|
||
|
||
# 峰值测试 - 投票开始瞬间 (80并发)
|
||
peak:
|
||
target: "http://127.0.0.1:3000"
|
||
phases:
|
||
- name: "预热"
|
||
duration: 3
|
||
arrivalRate: 10
|
||
- name: "峰值爬升"
|
||
duration: 5
|
||
arrivalRate: 20
|
||
rampTo: 80
|
||
- name: "峰值维持"
|
||
duration: 15
|
||
arrivalRate: 80
|
||
- name: "冷却"
|
||
duration: 5
|
||
arrivalRate: 10
|
||
|
||
# 压力测试 - 1.5倍余量 (120并发)
|
||
stress:
|
||
target: "http://127.0.0.1:3000"
|
||
phases:
|
||
- name: "预热"
|
||
duration: 5
|
||
arrivalRate: 20
|
||
- name: "压力爬升"
|
||
duration: 10
|
||
arrivalRate: 40
|
||
rampTo: 120
|
||
- name: "压力维持"
|
||
duration: 15
|
||
arrivalRate: 120
|
||
- name: "冷却"
|
||
duration: 5
|
||
arrivalRate: 20
|
||
|
||
# 现场模拟 - 100人年会场景(分散入场,更真实)
|
||
gala:
|
||
target: "http://127.0.0.1:3000"
|
||
phases:
|
||
- name: "陆续入场 (10秒)"
|
||
duration: 10
|
||
arrivalRate: 5
|
||
rampTo: 30 # 10秒内从5人/秒增加到30人/秒
|
||
- name: "投票高峰期 (60秒)"
|
||
duration: 60
|
||
arrivalRate: 15 # 持续15人/秒,模拟持续投票
|
||
- name: "结束离场 (10秒)"
|
||
duration: 10
|
||
arrivalRate: 5
|
||
|
||
# ============================================================================
|
||
# 测试场景定义
|
||
# ============================================================================
|
||
|
||
scenarios:
|
||
# 场景 1: 完整投票流程 (权重70%) - 模拟正常用户入场、投票、停留
|
||
- name: "完整投票流程"
|
||
weight: 7
|
||
engine: socketio
|
||
flow:
|
||
- function: "generateUserId"
|
||
- function: "randomEntryDelay"
|
||
- think: "{{ entryDelay }}" # 随机 0.1-3 秒后连接,模拟分散入场
|
||
- emit:
|
||
channel: "connection:join"
|
||
data:
|
||
userId: "{{ userId }}"
|
||
userName: "压测用户-{{ userId }}"
|
||
role: "user"
|
||
department: "测试部门"
|
||
- think: 0.5
|
||
- loop:
|
||
- function: "selectRandomProgram"
|
||
- function: "selectRandomTicketType"
|
||
- emit:
|
||
channel: "vote:submit"
|
||
data:
|
||
candidateId: "{{ selectedProgram }}"
|
||
category: "{{ selectedTicket }}"
|
||
localId: "{{ $uuid }}"
|
||
- function: "randomVoteDelay"
|
||
- think: "{{ voteDelay }}" # 随机 0.2-0.8 秒投票间隔
|
||
count: 5
|
||
- think: 2 # 投票后停留 2 秒
|
||
|
||
# 场景 2: 快速连投 (权重20%) - 模拟积极投票用户
|
||
- name: "快速连投压力"
|
||
weight: 2
|
||
engine: socketio
|
||
flow:
|
||
- function: "generateUserId"
|
||
- function: "randomEntryDelay"
|
||
- think: "{{ entryDelay }}" # 随机 0.1-3 秒后连接
|
||
- emit:
|
||
channel: "connection:join"
|
||
data:
|
||
userId: "{{ userId }}"
|
||
userName: "速投用户-{{ userId }}"
|
||
role: "user"
|
||
department: "压力测试"
|
||
- loop:
|
||
- function: "selectRandomProgram"
|
||
- function: "selectRandomTicketType"
|
||
- emit:
|
||
channel: "vote:submit"
|
||
data:
|
||
candidateId: "{{ selectedProgram }}"
|
||
category: "{{ selectedTicket }}"
|
||
localId: "{{ $uuid }}"
|
||
- think: 0.15
|
||
count: 7
|
||
- think: 1
|
||
|
||
# 场景 3: 观望用户 (权重10%) - 只连接不投票或很少投票
|
||
- name: "观望用户"
|
||
weight: 1
|
||
engine: socketio
|
||
flow:
|
||
- function: "generateUserId"
|
||
- function: "randomLateEntryDelay"
|
||
- think: "{{ entryDelay }}" # 随机 0-5 秒后连接
|
||
- emit:
|
||
channel: "connection:join"
|
||
data:
|
||
userId: "{{ userId }}"
|
||
userName: "观望用户-{{ userId }}"
|
||
role: "user"
|
||
department: "观望组"
|
||
- think: 8 # 长时间停留
|