4. k6 脚本核心语法(二):参数化、环境变量与场景配置
在上一节掌握了基础请求与检查点之后,本节将深入 k6 脚本的四个关键进阶能力:参数化(使用内置变量 __VU 与 __ITER)、环境变量管理、场景(Scenario)配置,以及 ramping-arrival-rate 执行器的实战用法。这些能力是构建真实、可复用、高仿真压测脚本的基石。
4.1 参数化:使用 __VU 与 __ITER
在分布式压测中,每个虚拟用户(VU)的行为需要具备一定的差异性,避免所有 VU 在同一时刻执行完全相同的操作(即“惊群效应”)。k6 提供了两个内置变量来实现轻量级参数化:
| 变量 | 类型 | 含义 | 典型用途 |
|---|---|---|---|
__VU |
整数 | 当前虚拟用户的唯一编号(从 1 开始) | 按用户 ID 分配数据分片、模拟不同用户登录 |
__ITER |
整数 | 当前 VU 已执行的迭代次数(从 0 开始) | 控制循环进度、按迭代轮次切换测试数据 |
__VU 在 VU 生命周期内保持不变;__ITER 随每次迭代递增。两者组合可生成全局唯一的请求标识。
以下示例展示了如何利用 __VU 和 __ITER 构造动态请求体:
import http from 'k6/http';
import { check, sleep } from 'k6';
export default function () {
// 使用 __VU 和 __ITER 构造唯一的用户标识
const userId = `user_${__VU}_iter_${__ITER}`;
const payload = JSON.stringify({
username: userId,
action: 'search',
timestamp: Date.now()
});
const params = {
headers: { 'Content-Type': 'application/json' },
};
const res = http.post('http://test.k6.io/api/search', payload, params);
check(res, {
'status is 200': (r) => r.status === 200,
'response has data': (r) => r.body.length > 0,
});
sleep(1);
}
__VU 作为用户 ID 的种子,避免所有 VU 使用相同的测试账号导致服务端限流或数据冲突。
4.2 环境变量:灵活配置压测参数
环境变量允许你在不修改脚本代码的前提下,动态调整压测目标地址、阈值、数据文件路径等参数。k6 支持通过 __ENV 对象读取环境变量,并在命令行中使用 -e 标志注入。
脚本中读取环境变量:
import http from 'k6/http';
// 从环境变量读取目标 URL,若未设置则使用默认值
const BASE_URL = __ENV.TARGET_URL || 'http://default.test.k6.io';
const = __ENV. || 'dev-key';
export default function () {
const res = http.get(`${BASE_URL}/api/status`, {
headers: { 'Authorization': `Bearer ${}` },
});
console.log(`VU ${__VU} - Status: ${res.status}`);
}
命令行注入环境变量:
k6 run -e TARGET_URL=http://staging.example.com -e =prod-secret-123 script.js
| 场景 | 推荐使用环境变量 | 示例值 |
|---|---|---|
| 多环境切换 | TARGET_URL |
http://dev-api.example.com |
| 密钥管理 | / AUTH_ |
sk-xxxx |
| 数据文件路径 | DATA_FILE |
./test-data/users.csv |
| 压测持续时间 | TEST_DURATION |
5m |
.env 文件不被提交到版本控制。
4.3 场景(Scenario)配置:多策略压测
k6 的场景配置允许你在同一个脚本中定义多个独立的压测策略,每个场景可以拥有不同的执行器、VU 数量、持续时间以及标签。这使得你可以同时模拟“平稳负载”和“突发流量”两种模式。
场景配置的核心结构:
import http from 'k6/http';
export const options = {
scenarios: {
// 场景一:恒定负载
constant_load: {
executor: 'constant-vus',
vus: 10,
duration: '30s',
tags: { scenario_type: 'constant' },
},
// 场景二:突发流量
burst_traffic: {
executor: 'ramping-vus',
startVUs: 0,
stages: [
{ duration: '10s', target: 50 },
{ duration: '20s', target: 50 },
{ duration: '10s', target: 0 },
],
tags: { scenario_type: 'burst' },
startTime: '10s', // 延迟 10 秒启动
},
},
};
export default function () {
http.get('http://test.k6.io');
}
scenario_type 过滤指标,精确评估每种负载模式对系统的影响。
下表列出了 k6 支持的常用执行器及其适用场景:
| 执行器名称 | 行为描述 | 典型使用场景 |
|---|---|---|
constant-vus |
固定数量的 VU 持续运行 | 基准测试、持续负载验证 |
ramping-vus |
VU 数量按阶段递增/递减 | 容量测试、弹性伸缩测试 |
constant-arrival-rate |
固定速率发起迭代(忽略 VU 数量) | 吞吐量测试、API 限流验证 |
ramping-arrival-rate |
迭代速率按阶段递增/递减 | 尖峰流量模拟、压力爬坡测试 |
externally-controlled |
通过 k6 API 动态控制 VU 数量 | 自动化测试平台集成、实时调控 |
4.4 ramping-arrival-rate 执行器详解
ramping-arrival-rate 是 k6 中最强大的执行器之一,它控制的是每秒发起的迭代次数(即吞吐量),而不是 VU 的数量。这意味着 k6 会自动管理 VU 池,确保达到目标速率,非常适合模拟真实世界中随时间变化的用户请求量。
核心配置参数:
export const options = {
scenarios: {
traffic_spike: {
executor: 'ramping-arrival-rate',
startRate: 10, // 起始每秒 10 次迭代
timeUnit: '1s', // 速率的时间单位
preAllocatedVUs: 20, // 预分配的 VU 数量
maxVUs: 100, // 最大 VU 数量(弹性扩展上限)
stages: [
{ duration: '30s', target: 10 }, // 保持 10 rps
{ duration: '30s', target: 50 }, // 爬坡到 50 rps
{ duration: '60s', target: 50 }, // 维持高负载
{ duration: '30s', target: 0 }, // 降为零
],
},
},
};
preAllocatedVUs 设置为目标速率所需 VU 的 1.5~2 倍。
下面的 SVG 图展示了 ramping-arrival-rate 执行器在三个阶段中,速率与 VU 数量的动态变化关系:
4.5 综合实战:参数化 + 环境变量 + 场景配置
将上述三个知识点整合到一个完整的压测脚本中,实现一个支持多环境、多场景、动态参数的搜索接口压测:
import http from 'k6/http';
import { check, sleep } from 'k6';
// 从环境变量读取配置
const BASE_URL = __ENV.TARGET_URL || 'http://test.k6.io';
const SEARCH_TERM = __ENV.SEARCH_TERM || 'k6';
export const options = {
scenarios: {
// 场景一:恒定搜索负载
steady_search: {
executor: 'constant-vus',
vus: 5,
duration: '1m',
tags: { scenario: 'steady' },
},
// 场景二:搜索流量爬坡
search_spike: {
executor: 'ramping-arrival-rate',
startRate: 5,
timeUnit: '1s',
preAllocatedVUs: 10,
maxVUs: 50,
stages: [
{ duration: '20s', target: 5 },
{ duration: '30s', target: 30 },
{ duration: '10s', target: 0 },
],
tags: { scenario: 'spike' },
startTime: '10s',
},
},
};
export default function () {
// 使用 __VU 和 __ITER 构造差异化搜索请求
const query = `${SEARCH_TERM}_vu${__VU}_iter${__ITER}`;
const res = http.get(`${BASE_URL}/search?q=${encodeURIComponent(query)}`);
check(res, {
'search status is 200': (r) => r.status === 200,
'search results exist': (r) => r.body.includes('results'),
});
sleep(0.5);
}
k6 run -e TARGET_URL=http://staging.example.com -e SEARCH_TERM=performance search-test.js
通过本节的学习,你已经掌握了 k6 脚本中参数化、环境变量、场景配置以及 ramping-arrival-rate 执行器的核心用法。这些技能将帮助你在后续的分布式压测实战中,构建出更加真实、灵活且可复用的压测脚本。