k6 场景的使用
(Grafana k6 登堂入室, Part 10)
发表于 2026-03
场景 -> Scenarios
什么是场景
前面的文章在介绍 HTTP 请求标签时简单提过 scenario,这篇来详细展开。
场景(Scenarios)用于精细控制 VU 和迭代的调度方式。通过场景,你可以在同一个脚本中模拟不同的负载模式——比如一部分用户稳定访问首页,另一部分用户以递增的速率发起搜索请求。
场景的好处:
- 灵活组织测试逻辑:一个脚本可以声明多个场景,每个场景独立执行不同的 JavaScript 函数
- 模拟真实流量:每个场景可以使用不同的 VU 和迭代调度模式
- 并行或顺序执行:场景之间默认并行运行,也可以通过
startTime控制先后顺序 - 独立的结果分析:每个场景可以设置独立的环境变量和指标标签
配置场景
在 options 对象中使用 scenarios 来配置。每个场景的名称必须唯一:
export const options = {
scenarios: {
example_scenario: {
// 执行器名称
executor: 'shared-iterations',
// 通用配置
startTime: '10s',
gracefulStop: '5s',
env: { EXAMPLEVAR: 'testing' },
tags: { example_tag: 'testing' },
// 执行器特有配置
vus: 10,
iterations: 200,
maxDuration: '10s',
},
another_scenario: {
/*...*/
},
},
};
场景的通用选项如下:
| 选项 | 类型 | 说明 | 默认值 |
|---|---|---|---|
executor(必填) |
string | 执行器名称 | - |
startTime |
string | 相对于测试开始的延迟时间 | "0s" |
gracefulStop |
string | 迭代结束前的等待时间 | "30s" |
exec |
string | 要执行的导出函数名 | "default" |
env |
object | 场景专属的环境变量 | {} |
tags |
object | 场景专属的标签 | {} |
执行器
每个场景的核心是执行器(Executor),它决定了负载的调度方式。k6 提供了 7 种执行器,分三大类:
按迭代次数
shared-iterations:固定总迭代次数,由多个 VU 共享。跑得快的 VU 会多分到一些迭代per-vu-iterations:每个 VU 各自执行固定次数的迭代
按 VU 数量
constant-vus:固定数量的 VU,在指定时间内尽可能多地执行迭代ramping-vus:VU 数量按阶段递增或递减
按到达率
constant-arrival-rate:以固定速率启动新迭代,不管上一次迭代是否完成ramping-arrival-rate:到达率按阶段变化externally-controlled:通过 k6 REST API 或 CLI 在运行时动态调整
开放模型 vs 封闭模型
这 7 种执行器背后有两种调度模型,理解这个区别对设计压测很重要。
封闭模型(Closed Model)
constant-vus 和 ramping-vus 属于封闭模型——上一次迭代结束后,下一次迭代才开始。这意味着被测系统的响应时间会影响实际吞吐量:系统越慢,迭代完成得越慢,新请求的到达率也就越低。
export const options = {
scenarios: {
closed_model: {
executor: 'constant-vus',
vus: 1,
duration: '1m',
},
},
};
export default function () {
// 这个请求大约需要 6 秒
// 所以 1 分钟内大约只能完成 10 次迭代
http.get('https://quickpizza.grafana.com/api/delay/6');
}
在某些测试文献中,这个问题被称为 "coordinated omission"——系统越慢,压力反而越小,这和真实场景可能不一致。
开放模型(Open Model)
constant-arrival-rate 和 ramping-arrival-rate 属于开放模型——新迭代的启动和上一次迭代是否完成无关。即使被测系统变慢,请求到达率也保持不变(或按配置变化)。
import http from 'k6/http';
export const options = {
scenarios: {
open_model: {
executor: 'constant-arrival-rate',
rate: 1,
timeUnit: '1s',
duration: '1m',
preAllocatedVUs: 20,
},
},
};
export default function () {
// 不管这个请求多慢,新迭代都会以每秒 1 次的速率启动
// 1 分钟内会产生 60 次迭代
http.get('https://quickpizza.grafana.com/api/delay/6');
}
如果你的目标是模拟固定的请求到达率(比如每秒 100 个请求),用开放模型;如果你的目标是模拟固定数量的并发用户,用封闭模型。
完整示例
下面的脚本组合了两个场景,演示顺序执行:
import http from 'k6/http';
export const options = {
scenarios: {
shared_iter_scenario: {
executor: 'shared-iterations',
vus: 10,
iterations: 100,
startTime: '0s',
},
per_vu_scenario: {
executor: 'per-vu-iterations',
vus: 10,
iterations: 10,
startTime: '10s',
},
},
};
export default function () {
http.get('https://test.k6.io/');
}
shared_iter_scenario立即开始,10 个 VU 共享 100 次迭代per_vu_scenario在 10 秒后启动,10 个 VU 各执行 10 次迭代
运行后 k6 会分别报告每个场景的指标:
scenarios: (100.00%) 2 scenarios, 20 max VUs, 10m40s max duration (incl. graceful stop):
* shared_iter_scenario: 100 iterations shared among 10 VUs
* per_vu_scenario: 10 iterations for each of 10 VUs (startTime: 10s)
输出结果中还会按场景分别列出 HTTP 指标,方便对比分析。
lyyyuna 沪ICP备2025110782号-1