Files
company-celebration/packages/server/load-test/vote-load-test.yaml
empty 5c5d0ad85c feat: 优化100人并发投票支持 + 修复奖项名称硬编码问题
服务端优化:
- 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 倍现场负载
2026-01-29 00:09:03 +08:00

209 lines
5.8 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ============================================================================
# 年会互动大屏系统 - 投票压力测试配置 (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 # 长时间停留