/** * Artillery 压力测试处理器 * 用于生成测试数据和自定义逻辑 * * 注意:使用 CommonJS 格式以兼容 Artillery */ // 节目ID列表 const programIds = [ 'p1', 'p2', 'p3', 'p4', 'p5', 'p6', 'p7', ]; // 奖项票种列表 (与 shared/constants 一致) const ticketTypes = [ 'creative', 'visual', 'atmosphere', 'performance', 'teamwork', 'popularity', 'potential', ]; // 用户计数器 (确保每个虚拟用户有唯一ID) let userCounter = 0; /** * 生成唯一用户ID */ function generateUserId(userContext, events, done) { userCounter++; const timestamp = Date.now(); userContext.vars.userId = `stress_user_${timestamp}_${userCounter}`; userContext.vars.voteIndex = 0; // 初始化投票索引 userContext.vars.usedTickets = []; // 已使用的票种 return done(); } /** * 随机选择一个节目 */ function selectRandomProgram(userContext, events, done) { const randomIndex = Math.floor(Math.random() * programIds.length); userContext.vars.selectedProgram = programIds[randomIndex]; return done(); } /** * 随机选择一个未使用的票种 * 符合业务逻辑:每种票只能用一次 */ function selectRandomTicketType(userContext, events, done) { const usedTickets = userContext.vars.usedTickets || []; const availableTickets = ticketTypes.filter(t => !usedTickets.includes(t)); if (availableTickets.length === 0) { // 所有票已用完,重置 (用于压测场景) userContext.vars.usedTickets = []; userContext.vars.selectedTicket = ticketTypes[0]; } else { const randomIndex = Math.floor(Math.random() * availableTickets.length); userContext.vars.selectedTicket = availableTickets[randomIndex]; userContext.vars.usedTickets.push(availableTickets[randomIndex]); } return done(); } /** * 顺序选择票种 (确保不重复) */ function selectNextTicketType(userContext, events, done) { const voteIndex = userContext.vars.voteIndex || 0; userContext.vars.selectedTicket = ticketTypes[voteIndex % ticketTypes.length]; userContext.vars.voteIndex = voteIndex + 1; return done(); } /** * 记录投票结果 (用于调试) */ function logVoteResult(userContext, events, done) { const { userId, selectedProgram, selectedTicket } = userContext.vars; console.log(`[VOTE] User: ${userId} -> Program: ${selectedProgram} (${selectedTicket})`); return done(); } /** * 生成随机延迟 (模拟真实用户行为) */ function randomDelay(userContext, events, done) { const minDelay = 100; // 最小 100ms const maxDelay = 500; // 最大 500ms const delay = Math.floor(Math.random() * (maxDelay - minDelay)) + minDelay; userContext.vars.thinkTime = delay / 1000; // 转换为秒 return done(); } /** * 随机入场延迟 0.1-3秒 (模拟分散入场) */ function randomEntryDelay(userContext, events, done) { const delay = (Math.floor(Math.random() * 30) + 1) / 10; // 0.1 - 3.0 秒 userContext.vars.entryDelay = delay; return done(); } /** * 随机短延迟 0.2-0.8秒 (投票间隔) */ function randomVoteDelay(userContext, events, done) { const delay = (Math.floor(Math.random() * 6) + 2) / 10; // 0.2 - 0.8 秒 userContext.vars.voteDelay = delay; return done(); } /** * 随机入场延迟 0-5秒 (观望用户) */ function randomLateEntryDelay(userContext, events, done) { const delay = Math.floor(Math.random() * 50) / 10; // 0 - 5.0 秒 userContext.vars.entryDelay = delay; return done(); } /** * 顺序选择票种 - 确保每人投完7种不同的票(按顺序) * 对应7个奖项:creative, visual, atmosphere, performance, teamwork, popularity, potential */ function selectSequentialTicket(userContext, events, done) { const voteIndex = userContext.vars.voteIndex || 0; // 按顺序取票种,确保7票投给不同奖项 userContext.vars.selectedTicket = ticketTypes[voteIndex % ticketTypes.length]; userContext.vars.voteIndex = voteIndex + 1; return done(); } /** * 正常投票延迟 1-2秒(正常投票者) */ function randomNormalDelay(userContext, events, done) { const delay = (Math.floor(Math.random() * 10) + 10) / 10; // 1.0 - 2.0 秒 userContext.vars.normalDelay = delay; return done(); } /** * 长延迟 5-10秒(观望型用户,先不投) */ function randomLongDelay(userContext, events, done) { const delay = (Math.floor(Math.random() * 50) + 50) / 10; // 5.0 - 10.0 秒 userContext.vars.longDelay = delay; return done(); } /** * 慢速投票延迟 3-5秒(犹豫不决型) */ function randomSlowDelay(userContext, events, done) { const delay = (Math.floor(Math.random() * 20) + 30) / 10; // 3.0 - 5.0 秒 userContext.vars.slowDelay = delay; return done(); } /** * 在连接前打印信息 (调试用) */ function beforeConnect(requestParams, context, ee, next) { console.log(`[CONNECT] Connecting user: ${context.vars.userId}`); return next(); } /** * 处理响应 (调试用) */ function afterResponse(requestParams, response, context, ee, next) { if (response.body && response.body.error) { console.log(`[ERROR] ${context.vars.userId}: ${response.body.error}`); } return next(); } // CommonJS exports exports.generateUserId = generateUserId; exports.selectRandomProgram = selectRandomProgram; exports.selectRandomTicketType = selectRandomTicketType; exports.selectNextTicketType = selectNextTicketType; exports.selectSequentialTicket = selectSequentialTicket; exports.logVoteResult = logVoteResult; exports.randomDelay = randomDelay; exports.randomEntryDelay = randomEntryDelay; exports.randomVoteDelay = randomVoteDelay; exports.randomLateEntryDelay = randomLateEntryDelay; exports.randomNormalDelay = randomNormalDelay; exports.randomLongDelay = randomLongDelay; exports.randomSlowDelay = randomSlowDelay; exports.beforeConnect = beforeConnect; exports.afterResponse = afterResponse;