4. k6 核心 API:http.get、http.post、check、group、sleep、metrics(自定义指标)

k6 脚本的核心是 JavaScript 代码与 k6 内置 API 的交互。本章将深入剖析压测脚本中最常用的六个核心 API:http.get、http.post、check、group、sleep 以及自定义指标(metrics)。掌握这些 API 是编写复杂、可观测的多阶段压测场景的基础。

核心原则:k6 的 API 设计遵循“同步阻塞”模型。每个 HTTP 请求都是同步的,直到收到响应或超时才会执行下一行代码。这使得脚本逻辑清晰,易于理解和调试。

4.1 HTTP 请求:http.get 与 http.post

http.get(url, [params]) 和 http.post(url, body, [params]) 是发起 HTTP 请求的基石。它们返回一个 Response 对象,包含状态码、响应体、头部、耗时等信息。

API 必填参数 可选参数 (params 对象) 典型返回值
http.get(url) url (字符串) tags, headers, timeout, params.auth 等 Response 对象
http.post(url, body) url (字符串), body (字符串/对象) tags, headers, timeout, params.auth 等 Response 对象
import http from 'k6/http';

export default function () {
  // GET 请求
  let getRes = http.get('https://test-api.example.com/users');
  console.log(`GET status: ${getRes.status}`);

  // POST 请求,发送 JSON 数据
  let payload = JSON.stringify({ name: 'k6-user', role: 'tester' });
  let params = {
    headers: { 'Content-Type': 'application/json' },
    tags: { my_custom_tag: 'user-creation' }, // 用于指标标记
  };
  let postRes = http.post('https://test-api.example.com/users', payload, params);
  console.log(`POST status: ${postRes.status}`);
}
关键参数:params.tags 允许你为每个请求打上自定义标签,这在后续分析指标(如按标签过滤请求耗时)时至关重要,是实现精细化 SLO 监控的基础。

4.2 断言与验证:check

check 函数用于对响应结果进行断言。它不会中断脚本执行,但会记录断言的成功/失败次数,并暴露为内置指标 checks 和 checks_failed。这是实现 SLO 门禁中“功能正确性”验证的核心。

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

export default function () {
  let res = http.get('https://test-api.example.com/health');

  // 使用 check 进行多项断言
  check(res, {
    'status is 200': (r) => r.status === 200,
    'response body has "ok"': (r) => r.body.includes('ok'),
    'response time < 500ms': (r) => r.timings.duration < 500,
  });
}
check 特性 说明
非阻塞 断言失败不会抛出异常,脚本继续执行后续逻辑。
内置指标 每次 check 结果自动记录到 checks (通过数) 和 checks_failed (失败数) 指标。
分组统计 与 group 结合使用,可以按业务模块查看断言通过率。

4.3 业务逻辑分组:group

group(name, func) 用于将相关的操作(如多个 HTTP 请求、多个 check)组织到一个逻辑分组中。分组不会影响执行顺序,但会在最终报告中按组聚合指标(如请求耗时、吞吐量),极大提升报告的可读性。

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

export default function () {
  group('用户登录流程', function () {
    let loginRes = http.post('https://test-api.example.com/login', { user: 'test', pass: '123' });
    check(loginRes, { 'login success': (r) => r.status === 200 });
  });

  group('获取用户资料', function () {
    let profileRes = http.get('https://test-api.example.com/profile');
    check(profileRes, { 'profile fetched': (r) => r.status === 200 });
  });
}
注意:group 是纯逻辑分组,不提供事务回滚或隔离能力。它主要用于报告聚合和指标标记,不要将其与数据库事务或编程语言中的 try-catch 混淆。

4.4 用户思考时间:sleep

sleep(t) 函数用于模拟真实用户在操作之间的“思考时间”或“等待时间”。参数 t 是以秒为单位的浮点数。合理使用 sleep 可以避免压测流量过于集中,使负载模型更接近真实场景。

import { sleep } from 'k6';

export default function () {
  // 模拟用户浏览首页
  http.get('https://test-api.example.com/');
  sleep(1); // 思考 1 秒

  // 模拟用户搜索
  http.get('https://test-api.example.com/search?q=k6');
  sleep(2.5); // 思考 2.5 秒

  // 模拟用户提交表单
  http.post('https://test-api.example.com/order', { item: 'book' });
  sleep(0.5);
}
最佳实践:使用随机化的思考时间(如 sleep(Math.random() * 3 + 1))可以更真实地模拟用户行为,避免所有虚拟用户同时发起请求。

4.5 自定义指标:metrics

除了 k6 内置的指标(如 http_req_duration, vus),你可以通过 metrics 模块创建自定义指标,用于监控业务层面的特定数据,例如:数据库查询耗时、缓存命中率、业务错误码计数等。自定义指标是实现精细化 SLO 监控的关键。

k6 支持四种自定义指标类型:

指标类型 构造函数 适用场景 聚合方式
Counter new Counter(name) 计数类,如错误次数、请求总数 求和
Gauge new Gauge(name) 瞬时值,如当前连接池大小、队列深度 最小值/最大值/最后值
Rate new Rate(name) 比率类,如成功率、缓存命中率 通过数/总数
Trend new Trend(name) 分布类,如数据库查询耗时、响应体大小 最小值/最大值/平均值/百分位数
import { Counter, Trend } from 'k6/metrics';
import http from 'k6/http';

// 定义自定义指标
let myErrorCounter = new Counter('my_business_errors');
let myDbQueryDuration = new Trend('my_db_query_duration', true); // true 表示启用百分位计算

export default function () {
  let res = http.get('https://test-api.example.com/data');

  // 模拟记录业务错误
  if (res.status !== 200) {
    myErrorCounter.add(1); // 增加计数
  }

  // 模拟记录数据库查询耗时(假设从响应头中获取)
  let dbTime = parseFloat(res.headers['X-DB-Query-Time'] || '0');
  myDbQueryDuration.add(dbTime); // 记录耗时分布
}
SLO 门禁集成:自定义指标可以直接在 thresholds 中使用。例如,你可以设置一个 SLO 门禁规则:thresholds: { 'my_business_errors': ['count<10'] },确保在压测期间业务错误总数不超过 10 个。
k6 核心 API 交互流程 VU 虚拟用户入口 group("业务模块") http.get / http.post check(响应断言) 自定义指标 (Counter/Trend) sleep(思考时间) 报告聚合 / SLO 门禁 每个 VU 循环执行:分组 → 请求 → 断言 → 指标 → 思考

4.6 综合示例:多阶段压测脚本

以下示例整合了所有核心 API,展示了一个典型的多阶段压测脚本结构:

import http from 'k6/http';
import { check, group, sleep } from 'k6';
import { Counter, Trend } from 'k6/metrics';

let businessErrors = new Counter('business_errors');
let orderTrend = new Trend('order_processing_time');

export const options = {
  stages: [
    { duration: '30s', target: 20 },
    { duration: '1m', target: 20 },
    { duration: '30s', target: 0 },
  ],
  thresholds: {
    http_req_duration: ['p(95)<2000'],
    business_errors: ['count<5'],
  },
};

export default function () {
  group('浏览商品', function () {
    let res = http.get('https://test-api.example.com/products');
    check(res, { 'products page loaded': (r) => r.status === 200 });
    sleep(Math.random() * 2 + 1);
  });

  group('下单流程', function () {
    let startTime = Date.now();
    let orderRes = http.post('https://test-api.example.com/orders', JSON.stringify({ item: 'laptop' }), {
      headers: { 'Content-Type': 'application/json' },
    });
    let duration = Date.now() - startTime;
    orderTrend.add(duration);

    if (orderRes.status !== 201) {
      businessErrors.add(1);
    }
    check(orderRes, { 'order created': (r) => r.status === 201 });
    sleep(1);
  });
}
本章小结:http.get/post 发起请求,check 验证结果,group 组织逻辑,sleep 模拟思考,metrics 自定义业务指标。这五个 API 构成了 k6 压测脚本的骨架,是后续实现复杂场景和 SLO 门禁的基石。