4. k6 核心 API 详解:HTTP 方法与请求控制
k6 的 http 模块是执行容量压测的核心驱动。本章深入解析 http.get/post/put/delete 方法、参数传递、Headers 设置、Cookies 管理以及超时与重试机制,帮助你在巡检脚本中精确控制每一个请求行为。
4.1 HTTP 方法:get / post / put / delete
k6 为每个标准 HTTP 动词提供了独立的 API 方法,所有方法均返回一个 Response 对象,包含状态码、响应体、耗时等关键指标。
| 方法 | 签名 | 典型场景 |
|---|---|---|
http.get(url, [params]) |
GET 请求 |
查询资源、健康检查、巡检探活 |
http.post(url, body, [params]) |
POST 请求 |
创建资源、提交表单、登录认证 |
http.put(url, body, [params]) |
PUT 请求 |
全量更新资源、配置下发 |
http.del(url, [params]) |
DELETE 请求 |
删除资源、清理测试数据 |
巡检脚本最佳实践: 在容量压测中,
GET 和 POST 占比通常超过 80%。建议将 POST 请求的 body 参数化,避免硬编码导致脚本不可复用。
import http from 'k6/http';
import { check } from 'k6';
export default function () {
// GET 请求
let getRes = http.get('https://api.example.com/users/1');
check(getRes, { 'GET status is 200': (r) => r.status === 200 });
// POST 请求(JSON body)
let payload = JSON.stringify({ name: 'test_user', role: 'admin' });
let postRes = http.post('https://api.example.com/users', payload, {
headers: { 'Content-Type': 'application/json' },
});
check(postRes, { 'POST status is 201': (r) => r.status === 201 });
// PUT 请求
let putRes = http.put('https://api.example.com/users/1', payload);
check(putRes, { 'PUT status is 200': (r) => r.status === 200 });
// DELETE 请求
let delRes = http.del('https://api.example.com/users/1');
check(delRes, { 'DELETE status is 204': (r) => r.status === 204 });
}
4.2 参数传递:Query、Body 与 URL 参数
k6 支持三种参数传递方式,分别对应不同的 HTTP 语义。在巡检脚本中,参数化是避免请求重复和触发缓存穿透的关键手段。
- Query 参数: 直接拼接在 URL 中,或通过
params对象的params字段传递。 - Body 参数: 支持
string、Buffer、Object(自动 JSON 序列化)或FormData。 - URL 路径参数: 使用模板字符串动态拼接,适合 RESTful 风格。
import http from 'k6/http';
export default function () {
// Query 参数方式一:URL 拼接
let res1 = http.get('https://api.example.com/search?q=k6&page=1');
// Query 参数方式二:params 对象
let res2 = http.get('https://api.example.com/search', {
params: { q: 'k6', page: '1' },
});
// Body 参数:JSON 对象自动序列化
let res3 = http.post('https://api.example.com/orders', {
userId: 123,
items: ['sku_a', 'sku_b'],
});
// URL 路径参数:模板字符串
let userId = 42;
let res4 = http.get(`https://api.example.com/users/${userId}`);
}
参数传递避坑: 当使用
params 对象传递 Query 参数时,k6 会自动进行 URL 编码。如果参数值包含特殊字符(如 &、=),务必使用 params 对象而非手动拼接,避免破坏 URL 结构。
4.3 Headers 设置:全局与请求级
Headers 控制着请求的认证、内容协商、缓存策略等关键行为。k6 支持两种设置层级:全局默认 Headers 和 请求级 Headers,后者优先级更高。
| 层级 | 设置方式 | 作用域 | 覆盖规则 |
|---|---|---|---|
| 全局 | http.defaults.headers |
所有请求 | 被请求级同名 Header 覆盖 |
| 请求级 | params.headers |
单次请求 | 完全覆盖全局同名 Header |
import http from 'k6/http';
// 设置全局默认 Headers
http.defaults.headers = {
'User-Agent': 'k6-capacity-test/1.0',
'Accept': 'application/json',
};
export default function () {
// 请求级 Headers 会覆盖全局同名 Header
let res = http.get('https://api.example.com/protected', {
headers: {
'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIs...',
'X-Request-ID': `req-${__VU}-${__ITER}`, // 动态追踪 ID
},
});
}
安全提醒: 不要在脚本中硬编码 或 。建议通过环境变量注入:
__ENV.AUTH_,并在 CI/CD 流水线中安全传递。
4.4 Cookies 管理:自动与手动控制
k6 的 Cookie 管理分为 自动 Cookie Jar(默认启用)和 手动 Cookie 控制。在容量压测中,理解 Cookie 行为对模拟有状态用户至关重要。
import http from 'k6/http';
import { check } from 'k6';
export default function () {
// 自动 Cookie Jar:登录后自动携带 Session
let loginRes = http.post('https://api.example.com/login', {
username: 'test', password: 'pass',
});
check(loginRes, { 'login success': (r) => r.status === 200 });
// 后续请求自动携带 Cookie
let profileRes = http.get('https://api.example.com/profile');
check(profileRes, { 'profile access': (r) => r.status === 200 });
}
4.5 超时与重试机制
在容量压测中,网络抖动和系统过载是常态。k6 提供了精细的超时控制和灵活的重试策略,确保巡检脚本在异常条件下仍能稳定运行。
4.5.1 超时设置
超时分为三个独立维度,分别控制不同阶段的等待时间:
| 参数 | 默认值 | 说明 |
|---|---|---|
timeout |
60s |
整个请求的完成超时(连接 + 发送 + 等待 + 接收) |
connectTimeout |
10s |
TCP 连接建立超时 |
tlsHandshakeTimeout |
10s |
TLS 握手超时 |
import http from 'k6/http';
export default function () {
let res = http.get('https://slow-api.example.com/data', {
timeout: '30s', // 总超时 30 秒
connectTimeout: '5s', // 连接超时 5 秒
tlsHandshakeTimeout: '5s', // TLS 握手超时 5 秒
});
}
4.5.2 重试机制
k6 本身不内置自动重试,但可以通过 check + 循环实现轻量级重试逻辑。对于需要严格重试的场景,推荐使用 k6/execution 模块控制重试次数和间隔。
import http from 'k6/http';
import { sleep } from 'k6';
const MAX_RETRIES = 3;
const RETRY_DELAY = 1; // 秒
export default function () {
let retries = 0;
let success = false;
while (retries < MAX_RETRIES && !success) {
let res = http.get('https://api.example.com/unstable', {
timeout: '10s',
});
if (res.status === 200) {
success = true;
console.log(`Request succeeded on attempt ${retries + 1}`);
} else {
retries++;
console.warn(`Attempt ${retries} failed with status ${res.status}`);
if (retries < MAX_RETRIES) {
sleep(RETRY_DELAY * retries); // 指数退避
}
}
}
if (!success) {
console.error('All retries exhausted');
}
}
巡检脚本重试策略:
- 幂等请求(GET / PUT / DELETE): 建议重试 2-3 次,使用指数退避(1s, 2s, 4s)。
- 非幂等请求(POST 创建资源): 谨慎重试,需配合幂等键(Idempotency-Key)防止重复创建。
- 超时类错误: 优先增加
timeout值,而非盲目重试。
4.6 综合示例:巡检脚本中的 HTTP 请求编排
以下示例整合了本章所有核心 API,展示一个完整的容量压测巡检请求流程:
import http from 'k6/http';
import { check, sleep } from 'k6';
// 全局配置
http.defaults.headers = {
'Accept': 'application/json',
'User-Agent': 'k6-capacity-inspection/2.0',
};
export default function () {
// 1. 登录(POST + Cookie 自动管理)
let loginPayload = { username: `user_${__VU}`, password: 'test123' };
let loginRes = http.post('https://api.example.com/auth/login', loginPayload, {
timeout: '15s',
});
check(loginRes, { 'login 200': (r) => r.status === 200 });
// 2. 查询资源列表(GET + Query 参数)
let listRes = http.get('https://api.example.com/items', {
params: { page: 1, limit: 50 },
timeout: '10s',
});
check(listRes, { 'list 200': (r) => r.status === 200 });
// 3. 创建资源(POST + 自定义 Header)
let createPayload = JSON.stringify({ name: `item_${__ITER}`, type: 'test' });
let createRes = http.post('https://api.example.com/items', createPayload, {
headers: { 'Content-Type': 'application/json', 'X-Idempotency-Key': `key_${__VU}_${__ITER}` },
timeout: '20s',
});
check(createRes, { 'create 201': (r) => r.status === 201 });
// 4. 更新资源(PUT)
let updateRes = http.put(`https://api.example.com/items/${__VU}`, createPayload, {
timeout: '10s',
});
check(updateRes, { 'update 200': (r) => r.status === 200 });
// 5. 删除资源(DELETE + 重试)
let delRetries = 0;
while (delRetries < 2) {
let delRes = http.del(`https://api.example.com/items/${__VU}`, { timeout: '8s' });
if (check(delRes, { 'delete 204': (r) => r.status === 204 })) break;
delRetries++;
sleep(1);
}
sleep(1);
}
巡检脚本设计原则: 每个 VU 使用独立的
__VU 和 __ITER 构造请求数据,避免请求冲突。超时设置应比生产环境 P99 响应时间高 50%,防止正常波动触发误报。