3. k6 核心概念:VU、迭代、指标、阈值与检查
在开始编写复杂的峰值流量回放脚本之前,必须牢固掌握 k6 的五大核心概念。它们是理解 k6 如何模拟用户、如何收集数据、以及如何判定测试是否通过的基础。本章将逐一拆解这些概念,并展示它们在实际回放场景中的协作关系。
3.1 核心概念全景图
下面的 SVG 图展示了 k6 测试执行的核心流程:VU 执行 迭代,迭代中运行 检查,同时 k6 自动收集 指标,最终由 阈值 判定测试结果是否达标。
3.2 VU(虚拟用户)
VU(Virtual User) 是 k6 中模拟真实用户行为的并发执行单元。每个 VU 独立运行 JavaScript 脚本,拥有自己的内存空间和上下文。
关键理解:VU 不是线程,也不是进程,而是 k6 使用 Go 协程(goroutine)实现的轻量级并发单元。单台机器可以轻松运行数千甚至数万 VU。
3.2.1 VU 的生命周期
| 阶段 | 说明 | 代码示例 |
|---|---|---|
| 初始化 | 加载模块、初始化配置,不计入测试时间 | import http from 'k6/http'; |
| VU 启动 | 执行 export default function 外的代码,每个 VU 执行一次 |
const BASE_URL = 'https://api.example.com'; |
| 迭代执行 | 反复执行 default 函数,直到测试结束 |
export default function() { ... } |
| VU 释放 | 测试结束后,VU 被回收,资源释放 | 自动完成 |
3.2.2 配置 VU 数量
通过 --vus 或 options 中的 vus 字段指定并发 VU 数量:
// 方式一:命令行参数
k6 run --vus 100 script.js
// 方式二:options 配置
export const options = {
vus: 100,
duration: '30s',
};
峰值回放提示:在峰值流量回放中,VU 数量应基于生产环境的历史峰值并发数进行设置。建议从 50% 峰值开始,逐步增加到 100% 甚至 120%,以验证系统的弹性边界。
3.3 迭代(Iterations)
迭代 是每个 VU 执行一次 export default function 的完整过程。迭代是 k6 中最基本的执行单元。
3.3.1 迭代控制模式
| 模式 | 配置方式 | 适用场景 |
|---|---|---|
| 基于时长 | duration: '30s' |
持续负载测试、稳定性测试 |
| 基于迭代次数 | iterations: 1000 |
功能验证、基准测试 |
| 混合模式 | stages 分段配置 |
峰值流量回放、阶梯负载 |
3.3.2 迭代与 VU 的关系
- 1 个 VU 可以执行 多次迭代(串行执行)。
- 多个 VU 同时执行各自的迭代(并行执行)。
- 总迭代次数 = VU 数量 × 每个 VU 执行的迭代次数。
// 示例:100 个 VU,每个 VU 执行 10 次迭代,总计 1000 次迭代
export const options = {
vus: 100,
iterations: 1000,
};
3.4 指标(Metrics)
指标 是 k6 自动收集的性能数据点。k6 内置了丰富的指标类型,覆盖请求、时间、速率等多个维度。
3.4.1 内置指标分类
| 指标类型 | 指标名称 | 说明 | 单位 |
|---|---|---|---|
| 计数器 | http_reqs |
HTTP 请求总数 | 次 |
iterations |
迭代完成总数 | 次 | |
data_received |
接收数据总量 | 字节 | |
| 速率 | http_req_rate |
每秒 HTTP 请求数 | req/s |
iteration_rate |
每秒迭代完成数 | iter/s | |
data_received_rate |
每秒接收数据速率 | bytes/s | |
| 趋势 | http_req_duration |
HTTP 请求总耗时 | ms |
http_req_waiting |
TTFB(首字节时间) | ms | |
http_req_connecting |
TCP 连接建立时间 | ms | |
| 比率 | http_req_failed |
HTTP 请求失败率 | % |
3.4.2 自定义指标
除了内置指标,k6 允许通过 Trend、Counter、Gauge、Rate 创建自定义指标:
import { Trend, Counter } from 'k6/metrics';
const loginDuration = new Trend('login_duration');
const loginSuccess = new Counter('login_success_count');
export default function () {
const start = Date.now();
// ... 执行登录操作 ...
loginDuration.add(Date.now() - start);
loginSuccess.add(1);
}
3.5 阈值(Thresholds)
阈值 是定义在指标上的通过/失败条件。当指标值不满足阈值条件时,k6 会将测试标记为 失败,并返回非零退出码。
3.5.1 阈值语法
export const options = {
thresholds: {
'http_req_duration': ['p(95)<2000'], // 95% 的请求耗时小于 2000ms
'http_req_failed': ['rate<0.01'], // 失败率小于 1%
'checks': ['rate>=0.95'], // 检查通过率不低于 95%
},
};
3.5.2 常用阈值表达式
| 表达式 | 含义 | 峰值回放典型值 |
|---|---|---|
p(95)<2000 |
95 分位耗时小于 2 秒 | 根据 SLA 调整,通常 1000~3000ms |
p(99)<5000 |
99 分位耗时小于 5 秒 | 长尾请求容忍上限 |
avg<1000 |
平均耗时小于 1 秒 | 用户体验基准线 |
rate<0.01 |
失败率小于 1% | 严格场景可设为 0.001 |
count>=1000 |
请求总数不少于 1000 | 确保负载量达标 |
注意:阈值只影响测试结果的判定,不会自动停止测试。如需在阈值触发时中止测试,需配合
abortOnFail 和 delayAbortEval 参数使用。
3.6 检查(Checks)
检查 是 k6 中的断言机制,用于验证请求的响应是否符合预期。与阈值不同,检查是 逐次 执行的,而阈值是对 聚合结果 的判定。
3.6.1 检查的基本用法
import { check } from 'k6';
import http from 'k6/http';
export default function () {
const res = http.get('https://api.example.com/users');
check(res, {
'状态码为 200': (r) => r.status === 200,
'响应时间小于 500ms': (r) => r.timings.duration < 500,
'返回数据非空': (r) => r.body.length > 0,
});
}
3.6.2 检查与阈值的区别
| 维度 | 检查(Checks) | 阈值(Thresholds) |
|---|---|---|
| 作用粒度 | 单次请求/操作 | 整个测试的聚合结果 |
| 执行时机 | 迭代执行过程中 | 测试结束后计算 |
| 失败影响 | 仅记录,不中断测试 | 标记测试为失败 |
| 典型用途 | 验证业务逻辑正确性 | 验证性能 SLA |
| 输出形式 | 通过/失败次数 | 通过/失败布尔值 |
3.7 实战:峰值回放中的概念组合
下面的 SVG 图展示了在峰值流量回放场景中,VU、迭代、检查、指标和阈值如何协同工作:
3.8 本章小结
- VU 是并发执行的基本单位,每个 VU 独立运行脚本。
- 迭代 是 VU 执行一次
default函数的完整过程。 - 指标 由 k6 自动收集,无需手动埋点,涵盖请求、时间、速率等维度。
- 阈值 定义在指标上的通过/失败条件,用于判定测试结果。
- 检查 是逐次执行的断言,用于验证单次请求的正确性。
- 在峰值流量回放中,这五个概念协同工作:VU 模拟并发用户,迭代执行回放逻辑,检查验证业务正确性,指标记录性能数据,阈值判定是否达到 SLA。