3. k6 脚本核心语法(一):VU 与迭代概念、default 函数、http.get 请求、检查点(check)与阈值(threshold)入门

本章是 k6 脚本开发的起点。你将理解 k6 最核心的执行模型——虚拟用户(VU)与迭代(Iteration),掌握脚本入口函数 default 的写法,发起第一个 HTTP GET 请求,并通过检查点(check)和阈值(threshold)验证请求结果。这些概念将贯穿整个压测脚本开发过程。

3.1 VU 与迭代:k6 的执行模型

k6 采用“虚拟用户(VU)循环执行迭代”的并发模型。理解这个模型是编写正确脚本的前提。

核心公式: 总请求数 ≈ VU 数 × 每个 VU 的迭代次数 × 每次迭代中的请求数
概念 说明 类比
VU(虚拟用户) 模拟一个真实用户,独立运行 JavaScript 代码的并发实体 一个独立的“机器人”
迭代(Iteration) 每个 VU 从 default 函数开始到结束的一次完整执行 机器人完成一次“任务循环”
VU 数 同时运行的虚拟用户数量,通过 --vus 或 options 设置 机器人的数量
迭代次数 每个 VU 执行的迭代总数,通过 --iterations 或 options 设置 每个机器人跑多少轮
k6 执行模型:VU 与迭代 VU #1 迭代 1 迭代 2 迭代 3 …… 继续执行 VU #2 迭代 1 迭代 2 迭代 3 …… 继续执行 VU #N 迭代 1 迭代 2 迭代 3 …… 继续执行 每个 VU 独立、并发地执行自己的迭代序列,VU 之间不共享状态(默认)

3.2 default 函数:脚本的入口

k6 脚本的核心是一个名为 default 的导出函数。每个 VU 的每次迭代都会执行这个函数一次。脚本中只能有一个 default 函数。

import http from 'k6/http';
import { check, sleep } from 'k6';

// 每个 VU 的每次迭代都会执行 default 函数
export default function () {
  let res = http.get('https://test.k6.io');
  check(res, {
    '状态码为 200': (r) => r.status === 200,
  });
  sleep(1);
}
提示: default 函数之外的代码(如全局变量、导入语句、配置对象)只在脚本初始化阶段执行一次,不会被重复执行。这有助于节省资源,但要注意全局状态的管理。

3.3 发起 HTTP GET 请求

http.get(url, [params]) 是 k6 中最常用的请求方法。它返回一个 Response 对象,包含状态码、响应体、响应头等信息。

参数 类型 说明 示例
url string 请求的目标 URL 'https://api.example.com/users'
params(可选) object 包含 headers、tags、timeout 等配置 { headers: { 'Authorization': 'Bearer xxx' } }
import http from 'k6/http';

export default function () {
  // 基本 GET 请求
  let res = http.get('https://test.k6.io');

  // 带请求头的 GET 请求
  let resWithHeaders = http.get('https://api.example.com/data', {
    headers: {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
    },
    tags: { name: '获取数据' },  // 自定义标签,用于结果分类
  });

  console.log(`状态码: ${res.status}`);
  console.log(`响应体长度: ${res.body.length}`);
}

3.4 检查点(check):验证响应是否符合预期

check 函数用于对响应结果进行断言验证。它不会中断脚本执行,但会记录检查通过/失败的数量,并影响最终的阈值判定。

import http from 'k6/http';
import { check } from 'k6';

export default function () {
  let res = http.get('https://test.k6.io');

  // 单个检查
  check(res, {
    '状态码为 200': (r) => r.status === 200,
  });

  // 多个检查
  check(res, {
    '状态码为 200': (r) => r.status === 200,
    '响应时间 < 2000ms': (r) => r.timings.duration < 2000,
    '响应体包含 k6': (r) => r.body.includes('k6'),
  });
}
注意: check 失败不会抛出异常或停止 VU 执行。如果你需要根据检查结果做分支逻辑,请使用普通的 if 语句。check 只用于“记录和统计”。

3.5 阈值(threshold):定义通过/失败标准

阈值是 k6 中定义性能验收标准的方式。它在脚本的 options 中声明,基于内置指标或自定义检查结果来判定压测是否通过。

import http from 'k6/http';
import { check } from 'k6';
import { Rate } from 'k6/metrics';

// 自定义指标:记录检查失败率
let failureRate = new Rate('failed_checks');

export let options = {
  vus: 10,
  iterations: 100,
  thresholds: {
    // 内置指标:95% 的请求响应时间 < 1500ms
    http_req_duration: ['p(95)<1500'],
    // 内置指标:请求失败率 < 1%
    http_req_failed: ['rate<0.01'],
    // 自定义指标:检查失败率 < 5%
    'failed_checks': ['rate<0.05'],
  },
};

export default function () {
  let res = http.get('https://test.k6.io');
  let checkResult = check(res, {
    '状态码为 200': (r) => r.status === 200,
  });
  // 记录检查失败
  failureRate.add(!checkResult);
}
阈值表达式 含义 适用场景
p(95)<2000 95% 的请求响应时间低于 2000ms 响应时间达标验证
rate<0.01 失败率低于 1% 错误率控制
avg<1000 平均响应时间低于 1000ms 平均性能基线
count>=1000 总请求数至少达到 1000 压测量级验证
检查点(check)与阈值(threshold)工作流程 HTTP GET 请求 check() 验证 ✅ 检查通过 ❌ 检查失败 threshold() 判定 通过 / 失败 check 记录每次验证结果,threshold 基于聚合指标判定整体压测是否达标

3.6 综合示例:第一个完整的压测脚本

将以上知识点整合,编写一个完整的压测脚本:

import http from 'k6/http';
import { check, sleep } from 'k6';
import { Rate } from 'k6/metrics';

// 自定义指标:记录检查失败率
let failureRate = new Rate('check_failure_rate');

export let options = {
  vus: 5,                // 5 个虚拟用户
  iterations: 50,        // 总共执行 50 次迭代
  thresholds: {
    // 95% 的请求响应时间 < 2000ms
    http_req_duration: ['p(95)<2000'],
    // 请求失败率 < 1%
    http_req_failed: ['rate<0.01'],
    // 自定义检查失败率 < 10%
    'check_failure_rate': ['rate<0.1'],
  },
};

export default function () {
  // 1. 发起 GET 请求
  let res = http.get('https://test.k6.io');

  // 2. 执行检查点
  let checkPassed = check(res, {
    '状态码为 200': (r) => r.status === 200,
    '响应时间 < 3000ms': (r) => r.timings.duration < 3000,
    '页面包含 k6': (r) => r.body.includes('k6'),
  });

  // 3. 记录检查失败率
  failureRate.add(!checkPassed);

  // 4. 模拟用户思考时间
  sleep(1);
}
最佳实践: 在开发阶段,可以先使用 k6 run script.js 在本地运行少量迭代(如 --iterations 10)来验证脚本逻辑。确认检查点和阈值配置正确后,再增加 VU 数和迭代次数进行正式压测。

3.7 本章小结

  • VU 与迭代 是 k6 并发模型的基础,每个 VU 独立循环执行 default 函数。
  • default 函数 是脚本入口,每次迭代都会执行一次。
  • http.get() 发起 HTTP GET 请求,返回 Response 对象。
  • check() 用于验证响应结果,记录通过/失败次数。
  • threshold 定义性能验收标准,基于聚合指标判定压测是否通过。