K6 性能测试脚本编写

FreeGuideOnline 最新 2026-07-10

bash brew install k6


**Linux (Debian/Ubuntu)**
```bash
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 379CE192D401AB61
echo "deb https://dl.bintray.com/loadimpact/deb stable main" | sudo tee -a /etc/apt/sources.list
sudo apt update && sudo apt install k6

Windows (通过 Chocolatey)

choco install k6

使用 Docker

docker pull grafana/k6
docker run -i grafana/k6 run - <script.js

完成安装后,在终端输入 k6 version 验证是否成功。

第一个 K6 脚本

创建一个文件 script.js,编写以下代码:

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

export default function () {
  http.get('https://test-api.k6.io');
  sleep(1);
}

在终端运行:

k6 run script.js

你将看到控制台输出的请求结果和性能指标。下面我们来拆解这个脚本的每个部分。

脚本结构拆解

每一个 K6 脚本必须包含一个名为 default 的导出函数,它会在每次迭代中被执行。你可以导入多个内置模块:

  • k6/http:发送 HTTP 请求的核心模块
  • k6/sleep:固定等待时间
  • k6/check:断言与验证
  • k6/metrics:自定义指标
  • k6/options:全局测试配置

HTTP 请求的完整用法

GET 请求

import http from 'k6/http';

export default function () {
  const res = http.get('https://httpbin.test.k6.io/get');
  console.log(`状态码: ${res.status}`);
}

POST 请求(JSON 数据)

const url = 'https://httpbin.test.k6.io/post';
const payload = JSON.stringify({ name: 'k6', type: 'performance' });
const params = {
  headers: {
    'Content-Type': 'application/json',
  },
};
const res = http.post(url, payload, params);

带查询参数和认证的请求

const res = http.get('https://test-api.k6.io/public/crocodiles/', {
  headers: { Authorization: 'Bearer token123' },
  tags: { name: 'CrocodilesAPI' },
});

tags 可用于在测试结果中对不同请求进行分组分析。

使用检查点(Checks)进行响应验证

check 函数可以验证响应是否符合预期,但不会终止测试执行,只会影响通过率统计。

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

export default function () {
  const res = http.get('https://httpbin.test.k6.io/status/200');
  check(res, {
    '状态码为200': (r) => r.status === 200,
    '响应时间低于500ms': (r) => r.timings.duration < 500,
  });
}

如果所有检查都通过,该迭代的检查通过率为 100%;如果有一项失败,则标记为失败。

配置测试负载:options 对象

通过在脚本中定义 options 导出变量,可以控制虚拟用户数(VUs)、测试持续时间、迭代次数等。

export const options = {
  vus: 10,
  duration: '30s',
};

更精细的负载控制可以使用 stages(阶段式增加/减少):

export const options = {
  stages: [
    { duration: '1m', target: 50 },  // 在1分钟内上升到50个VUs
    { duration: '3m', target: 50 },  // 保持50个VUs运行3分钟
    { duration: '1m', target: 0 },   // 1分钟内降至0
  ],
};

你还可以设置阈值(thresholds)来定义性能 SLA,一旦违反相关条件,测试结果会被标记为失败。

export const options = {
  thresholds: {
    http_req_duration: ['p(95)<500'], // 95%的请求必须在500ms内完成
    checks: ['rate>0.9'],             // 检查通过率必须大于90%
  },
};

高级脚本技巧

动态数据与测试数据文件

你可以使用 open 函数加载 CSV 或 JSON 文件,实现数据驱动的测试:

import { SharedArray } from 'k6/data';

const users = new SharedArray('users', function () {
  return JSON.parse(open('./users.json'));
});

export default function () {
  const user = users[Math.floor(Math.random() * users.length)];
  let res = http.post('https://test-api.k6.io/auth/login', JSON.stringify(user), {
    headers: { 'Content-Type': 'application/json' },
  });
}

自定义指标

除了内置指标(如 http_req_duration),你还可以创建自定义指标用于跟踪业务数据:

import { Counter, Trend } from 'k6/metrics';

let loginCounter = new Counter('login_attempts');
let dataProcessingTime = new Trend('data_processing_time');

export default function () {
  let start = Date.now();
  // ... 业务逻辑
  dataProcessingTime.add(Date.now() - start);
  loginCounter.add(1);
}

使用生命周期的钩子

K6 提供四个生命周期函数:setupdefaultteardown 以及可选的 handleSummary

export function setup() {
  // 在所有 VU 执行之前运行一次,用于准备数据
  return { token: 'abc' };
}

export default function (data) {
  // 每个迭代接收 setup 返回的数据
  console.log(data.token);
}

export function teardown(data) {
  // 在所有迭代结束后运行一次,用于清理数据
}

export function handleSummary(data) {
  // 自定义结果摘要输出格式
  return {
    'summary.json': JSON.stringify(data),
    stdout: textSummary(data, { enableColors: true }),
  };
}

运行测试与结果解读

运行脚本时,可以使用以下常用参数:

k6 run --vus 100 --duration 10s script.js      # 从命令行覆盖VU与时长
k6 run -e MY_ENV=production script.js           # 注入环境变量
k6 run --out json=result.json script.js         # 将详细结果导出为JSON

测试结束后,控制台会输出类似下面的摘要:

     data_received..............: 12 MB  (2.4 MB/s)
     data_sent..................: 1.2 MB (249 kB/s)
     http_req_blocked...........: avg=3.12ms   min=1µs   med=5µs    max=500ms  p(90)=10µs   p(95)=20µs  
     http_req_connecting........: avg=1.09ms   min=0s    med=0s     max=450ms  p(90)=0s     p(95)=0s    
     http_req_duration..........: avg=220ms    min=150ms med=200ms  max=1.2s   p(90)=350ms  p(95)=500ms 
     http_req_receiving.........: avg=70µs     min=16µs  med=40µs   max=3ms    p(90)=80µs   p(95)=100µs 
     http_req_waiting...........: avg=219.9ms  min=149ms med=200ms  max=1.2s   p(90)=349ms  p(95)=499ms
     http_reqs..................: 15000 (300/s)
     iterations.................: 15000 (300/s)
     vus........................: 100
     vus_max....................: 100