live-forum/server/k6/scenario-browse.js
2026-03-24 11:27:37 +08:00

215 lines
6.2 KiB
JavaScript
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.

/**
* k6 压测脚本 - 场景一:普通用户浏览
*
* 模拟用户行为:
* 1. 进入首页 -> 获取轮播图、榜单分类、主播榜单、直播列表
* 2. 进入社区 -> 获取帖子列表
* 3. 查看帖子 -> 获取帖子详情、评论列表
* 4. 翻页浏览 -> 加载更多帖子
*
* 运行命令:
* k6 run --out web-dashboard scenario-browse.js
*
* 快速测试:
* k6 run --out web-dashboard -e QUICK_TEST=true scenario-browse.js
*/
import { BROWSE_OPTIONS, QUICK_TEST_OPTIONS, TEST_DATA } from './config.js';
import {
httpGet,
checkResponse,
parseResponse,
thinkTime,
shortWait,
getTokenCount,
API
} from './utils/helpers.js';
// ============================================
// 压测配置
// ============================================
const isQuickTest = __ENV.QUICK_TEST === 'true';
export const options = isQuickTest ? QUICK_TEST_OPTIONS : BROWSE_OPTIONS;
// ============================================
// 初始化阶段(每个 VU 执行一次)
// ============================================
export function setup() {
const tokenCount = getTokenCount();
console.log(`========================================`);
console.log(`场景:普通用户浏览(读操作为主)`);
console.log(`Token 数量:${tokenCount}`);
console.log(`模式:${isQuickTest ? '快速测试' : '正式压测'}`);
console.log(`========================================`);
if (tokenCount === 0) {
throw new Error('没有可用的 Token请先在 tokens.txt 中添加 Token');
}
return { tokenCount };
}
// ============================================
// 主测试函数(每个 VU 循环执行)
// ============================================
export default function(data) {
const vuId = __VU;
// 存储动态获取的数据
let postIds = [];
// ==================
// 步骤1: 首页数据加载
// ==================
// 1.1 获取轮播图
let res = httpGet(API.HOME.BANNERS, {}, vuId);
checkResponse(res, 'GetBanners');
shortWait();
// 1.2 获取主播榜单分类
res = httpGet(API.HOME.CATEGORIES, {}, vuId);
checkResponse(res, 'StreamerCategories');
shortWait();
// 1.3 获取主播榜单
res = httpGet(API.HOME.RANKINGS, {
category: TEST_DATA.category,
limit: TEST_DATA.rankingLimit,
}, vuId);
checkResponse(res, 'Rankings');
shortWait();
// 1.4 获取直播中主播列表
res = httpGet(API.HOME.LIVE_STREAMERS, {
page: 1,
pageSize: 10,
}, vuId);
checkResponse(res, 'LiveStreamers');
// 模拟用户在首页浏览的思考时间
thinkTime();
// ==================
// 步骤2: 社区帖子列表
// ==================
// 2.1 获取帖子列表第1页
res = httpGet(API.POSTS.LIST, {
SortType: 1,
PageIndex: 1,
PageSize: TEST_DATA.pageSize,
}, vuId);
checkResponse(res, 'GetPosts-Page1');
// 解析帖子列表提取帖子ID
const postsData = parseResponse(res);
if (postsData && postsData.items && postsData.items.length > 0) {
postIds = postsData.items.map(item => item.postId);
}
thinkTime();
// 2.2 获取帖子列表第2页模拟翻页
res = httpGet(API.POSTS.LIST, {
SortType: 1,
PageIndex: 2,
PageSize: TEST_DATA.pageSize,
}, vuId);
checkResponse(res, 'GetPosts-Page2');
// 追加更多帖子ID
const postsData2 = parseResponse(res);
if (postsData2 && postsData2.items && postsData2.items.length > 0) {
postIds = postIds.concat(postsData2.items.map(item => item.postId));
}
thinkTime();
// ==================
// 步骤3: 查看帖子详情
// ==================
if (postIds.length > 0) {
// 随机选择一个帖子查看详情
const randomIndex = Math.floor(Math.random() * postIds.length);
const postId = postIds[randomIndex];
// 3.1 获取帖子详情
res = httpGet(API.POSTS.DETAIL, {
PostId: postId,
}, vuId);
checkResponse(res, 'GetPostDetail');
shortWait();
// 3.2 获取评论列表第1页
res = httpGet(API.COMMENTS.LIST, {
PostId: postId,
SortType: 2,
PageIndex: 1,
PageSize: TEST_DATA.commentPageSize,
}, vuId);
checkResponse(res, 'GetPostComments-Page1');
thinkTime();
// 3.3 获取评论列表第2页模拟加载更多评论
res = httpGet(API.COMMENTS.LIST, {
PostId: postId,
SortType: 2,
PageIndex: 2,
PageSize: TEST_DATA.commentPageSize,
}, vuId);
checkResponse(res, 'GetPostComments-Page2');
thinkTime();
// 3.4 查看另一个帖子(如果有)
if (postIds.length > 1) {
const anotherIndex = (randomIndex + 1) % postIds.length;
const anotherPostId = postIds[anotherIndex];
res = httpGet(API.POSTS.DETAIL, {
PostId: anotherPostId,
}, vuId);
checkResponse(res, 'GetPostDetail-2');
shortWait();
res = httpGet(API.COMMENTS.LIST, {
PostId: anotherPostId,
SortType: 2,
PageIndex: 1,
PageSize: TEST_DATA.commentPageSize,
}, vuId);
checkResponse(res, 'GetPostComments-Another');
}
}
// ==================
// 步骤4: 查看更多排行
// ==================
res = httpGet(API.HOME.RANKINGS_MORE, {
category: TEST_DATA.category,
page: 1,
pageSize: 20,
}, vuId);
checkResponse(res, 'RankingsMore');
thinkTime();
}
// ============================================
// 结束阶段
// ============================================
export function teardown(data) {
console.log(`========================================`);
console.log(`压测结束`);
console.log(`========================================`);
}