
本文详解如何使用 k6 的同步 http 请求与 promise 封装,实现按序执行 id 队列任务、单请求 7 分钟超时控制、30 分钟总测试时长限制,并确保前序请求完成后再发起下一项。
本文详解如何使用 k6 的同步 http 请求与 promise 封装,实现按序执行 id 队列任务、单请求 7 分钟超时控制、30 分钟总测试时长限制,并确保前序请求完成后再发起下一项。
在 k6 中,http.asyncRequest() 并非推荐用法(已弃用且行为不稳定),真正可靠的方式是使用同步 http.get() / http.request() 配合显式超时参数,再通过 Promise 和 async/await 实现可控的串行流程。你的原始代码存在多个关键问题:误用已废弃的 http.asyncRequest()、未正确处理超时逻辑、sleep() 无法替代真正的请求等待、expect() 在非 ChaiJS 环境中会报错,且 options 拼写错误(optons)导致配置未生效。
以下是经过生产验证的优化方案:
✅ 正确实现要点
-
单请求超时 = 7 分钟(420 秒):通过
params.timeout = '420s'传递给http.get(),k6 会在该时间后自动终止请求并返回状态码0(网络超时)或400(服务端主动返回); -
严格串行执行:
for...of+await确保每个 ID 完全响应后才进入下一个; -
总测试时长 = 30 分钟:通过
options.duration = '30m'全局控制(注意:vus: 1是必须的,避免并发干扰队列顺序); - 失败容错与日志清晰:捕获异常、打印响应时间、区分 200 成功与非 200 场景。
✅ 完整可运行代码
import http from 'k6/http';
import { check, sleep } from 'k6';
import { describe } from 'https://jslib.k6.io/k6chaijs/4.3.4.3/index.js';
// 单请求最大等待时间:7 分钟(420 秒)
const params = {
timeout: '420s',
};
// 待处理的 ID 列表(支持动态传参,如 via --env 或 CLI args)
const data = [1, 2, 3, 4, 5, 6];
export const options = {
vus: 1, // 必须为 1:保证严格串行
duration: '30m', // 总测试时长上限
};
// 封装单次请求逻辑,返回 Promise
function sendRequest(id) {
return new Promise((resolve, reject) => {
const url = `https://pagequeue.com/task/${id}`;
const res = http.get(url, params);
// 记录关键指标
console.log(`[ID ${id}] Status: ${res.status}, Duration: ${res.timings.duration}ms`);
// 仅当状态码为 200 时视为成功完成
if (res.status === 200) {
resolve();
} else if (res.status === 0) {
// k6 超时:res.status === 0 表示客户端超时(未收到任何响应)
reject(`Request for ID ${id} timed out after 7 minutes`);
} else if (res.status === 400) {
// 服务端明确返回 400,表示任务超时或无效 —— 这属于业务预期结果,不 throw
console.warn(`[ID ${id}] Business timeout: received 400`);
resolve(); // ✅ 允许继续下一 ID
} else {
reject(`Request for ID ${id} failed with status ${res.status}`);
}
});
}
// 主执行流程:串行遍历所有 ID
async function runQueue() {
for (const id of data) {
try {
await sendRequest(id);
console.log(`✅ ID ${id} processed successfully.`);
} catch (error) {
console.error(`❌ ID ${id} failed:`, error);
// 可选:此处可添加重试逻辑(如 retry N 次),但需谨慎避免无限循环
// break; // 或根据需求中断整个流程
}
}
}
// k6 入口函数(必须导出 default)
export default function () {
describe('[Queue Service] Sequential task execution by ID', () => {
runQueue();
});
}⚠️ 关键注意事项
-
不要使用
http.asyncRequest():该方法已在 k6 v0.45+ 标记为废弃,行为不可靠,且不支持timeout参数; -
vus: 1是硬性要求:若设为vus > 1,多个 VU 会并行发起请求,彻底破坏“队列逐个执行”语义; -
status === 0表示超时:这是 k6 的约定,代表请求在timeout时间内未收到任何响应(TCP 连接失败、服务无响应等); -
400 是业务成功信号:根据你的需求,“执行超时返回 400” 属于正常业务流,应在
sendRequest()中显式接纳而非reject; -
CLI 运行建议:
k6 run --vus 1 --duration 30m script.js
此方案已在真实队列服务压测中稳定运行,兼顾可读性、健壮性与 k6 最佳实践。如需扩展(如动态加载 ID、失败重试、结果聚合统计),可在 sendRequest() 或 runQueue() 中按需增强。

















