k6

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

k6 Performance Testing

k6性能测试

Quick Start

快速开始

bash
undefined
bash
undefined

Install

Install

brew install k6 # macOS sudo apt install k6 # Ubuntu/Debian choco install k6 # Windows
brew install k6 # macOS sudo apt install k6 # Ubuntu/Debian choco install k6 # Windows

Run a test

Run a test

k6 run script.js k6 run --vus 10 --duration 30s script.js k6 run --out json=results.json script.js
undefined
k6 run script.js k6 run --vus 10 --duration 30s script.js k6 run --out json=results.json script.js
undefined

Basic Script Structure

基础脚本结构

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

export const options = {
  vus: 10,
  duration: '30s',
  thresholds: {
    http_req_duration: ['p(95)<500'],   // 95% of requests under 500ms
    http_req_failed: ['rate<0.01'],     // error rate under 1%
  },
};

export default function () {
  const res = http.get('https://test.k6.io');
  check(res, {
    'status is 200': (r) => r.status === 200,
    'response time OK': (r) => r.timings.duration < 500,
  });
  sleep(1);
}
javascript
import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  vus: 10,
  duration: '30s',
  thresholds: {
    http_req_duration: ['p(95)<500'],   // 95% of requests under 500ms
    http_req_failed: ['rate<0.01'],     // error rate under 1%
  },
};

export default function () {
  const res = http.get('https://test.k6.io');
  check(res, {
    'status is 200': (r) => r.status === 200,
    'response time OK': (r) => r.timings.duration < 500,
  });
  sleep(1);
}

Test Lifecycle

测试生命周期

javascript
export function setup() {
  // Runs once before all VUs — return data shared with VUs
  const token = getAuthToken();
  return { token };
}

export default function (data) {
  // Runs for each VU iteration — receives setup() return value
  http.get('https://api.example.com', {
    headers: { Authorization: `Bearer ${data.token}` },
  });
}

export function teardown(data) {
  // Runs once after all VUs finish
  console.log('Test complete');
}
javascript
export function setup() {
  // Runs once before all VUs — return data shared with VUs
  const token = getAuthToken();
  return { token };
}

export default function (data) {
  // Runs for each VU iteration — receives setup() return value
  http.get('https://api.example.com', {
    headers: { Authorization: `Bearer ${data.token}` },
  });
}

export function teardown(data) {
  // Runs once after all VUs finish
  console.log('Test complete');
}

HTTP Requests

HTTP请求

javascript
import http from 'k6/http';

// GET
const res = http.get('https://api.example.com/users');

// POST with JSON body
const payload = JSON.stringify({ name: 'test', value: 42 });
const params = { headers: { 'Content-Type': 'application/json' } };
const res = http.post('https://api.example.com/users', payload, params);

// PUT / PATCH / DELETE
http.put(url, body, params);
http.patch(url, body, params);
http.del(url, null, params);

// Batch requests (parallel)
const responses = http.batch([
  ['GET', 'https://api.example.com/users'],
  ['GET', 'https://api.example.com/posts'],
]);

// With auth
const res = http.get(url, {
  headers: { Authorization: 'Bearer token123' },
});

// Form data
const res = http.post(url, { username: 'user', password: 'pass' });

// File upload
const binFile = open('./image.png', 'b');
const res = http.post(url, {
  file: http.file(binFile, 'image.png', 'image/png'),
  field: 'value',
});
javascript
import http from 'k6/http';

// GET
const res = http.get('https://api.example.com/users');

// POST with JSON body
const payload = JSON.stringify({ name: 'test', value: 42 });
const params = { headers: { 'Content-Type': 'application/json' } };
const res = http.post('https://api.example.com/users', payload, params);

// PUT / PATCH / DELETE
http.put(url, body, params);
http.patch(url, body, params);
http.del(url, null, params);

// Batch requests (parallel)
const responses = http.batch([
  ['GET', 'https://api.example.com/users'],
  ['GET', 'https://api.example.com/posts'],
]);

// With auth
const res = http.get(url, {
  headers: { Authorization: 'Bearer token123' },
});

// Form data
const res = http.post(url, { username: 'user', password: 'pass' });

// File upload
const binFile = open('./image.png', 'b');
const res = http.post(url, {
  file: http.file(binFile, 'image.png', 'image/png'),
  field: 'value',
});

Checks and Thresholds

检查与阈值

javascript
import { check } from 'k6';

// Checks (soft assertions — don't stop test on failure)
const res = http.get(url);
check(res, {
  'status 200': (r) => r.status === 200,
  'body contains ID': (r) => r.body.includes('"id"'),
  'duration < 500ms': (r) => r.timings.duration < 500,
});

// Thresholds (hard pass/fail criteria)
export const options = {
  thresholds: {
    // HTTP metrics
    http_req_duration: ['p(90)<400', 'p(95)<800', 'avg<200'],
    http_req_failed: ['rate<0.05'],

    // Custom metric thresholds
    my_errors: ['count<10'],

    // Tag-based thresholds (specific endpoints)
    'http_req_duration{name:homepage}': ['p(95)<500'],

    // Abort test if threshold breached
    http_req_duration: [{ threshold: 'p(99)<3000', abortOnFail: true }],
  },
};
javascript
import { check } from 'k6';

// Checks (soft assertions — don't stop test on failure)
const res = http.get(url);
check(res, {
  'status 200': (r) => r.status === 200,
  'body contains ID': (r) => r.body.includes('"id"'),
  'duration < 500ms': (r) => r.timings.duration < 500,
});

// Thresholds (hard pass/fail criteria)
export const options = {
  thresholds: {
    // HTTP metrics
    http_req_duration: ['p(90)<400', 'p(95)<800', 'avg<200'],
    http_req_failed: ['rate<0.05'],

    // Custom metric thresholds
    my_errors: ['count<10'],

    // Tag-based thresholds (specific endpoints)
    'http_req_duration{name:homepage}': ['p(95)<500'],

    // Abort test if threshold breached
    http_req_duration: [{ threshold: 'p(99)<3000', abortOnFail: true }],
  },
};

Custom Metrics

自定义指标

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

const myErrors = new Counter('my_errors');
const activeUsers = new Gauge('active_users');
const successRate = new Rate('success_rate');
const reqDuration = new Trend('req_duration', true); // true = display in ms

export default function () {
  const res = http.get(url);
  if (res.status !== 200) myErrors.add(1);
  successRate.add(res.status === 200);
  reqDuration.add(res.timings.duration);
}
javascript
import { Counter, Gauge, Rate, Trend } from 'k6/metrics';

const myErrors = new Counter('my_errors');
const activeUsers = new Gauge('active_users');
const successRate = new Rate('success_rate');
const reqDuration = new Trend('req_duration', true); // true = display in ms

export default function () {
  const res = http.get(url);
  if (res.status !== 200) myErrors.add(1);
  successRate.add(res.status === 200);
  reqDuration.add(res.timings.duration);
}

Scenarios and Executors

场景与执行器

See
references/scenarios-executors.md
for full reference.
javascript
export const options = {
  scenarios: {
    // Constant VUs
    steady_load: {
      executor: 'constant-vus',
      vus: 50,
      duration: '5m',
    },
    // Ramping VUs (most common)
    ramp_up: {
      executor: 'ramping-vus',
      startVUs: 0,
      stages: [
        { duration: '2m', target: 100 },
        { duration: '5m', target: 100 },
        { duration: '2m', target: 0 },
      ],
    },
    // Constant arrival rate (requests per second)
    constant_rps: {
      executor: 'constant-arrival-rate',
      rate: 100,             // 100 iterations/sec
      timeUnit: '1s',
      duration: '5m',
      preAllocatedVUs: 50,
      maxVUs: 200,
    },
    // Per-VU iterations
    per_vu: {
      executor: 'per-vu-iterations',
      vus: 10,
      iterations: 100,
    },
  },
};
完整参考请查看
references/scenarios-executors.md
javascript
export const options = {
  scenarios: {
    // Constant VUs
    steady_load: {
      executor: 'constant-vus',
      vus: 50,
      duration: '5m',
    },
    // Ramping VUs (most common)
    ramp_up: {
      executor: 'ramping-vus',
      startVUs: 0,
      stages: [
        { duration: '2m', target: 100 },
        { duration: '5m', target: 100 },
        { duration: '2m', target: 0 },
      ],
    },
    // Constant arrival rate (requests per second)
    constant_rps: {
      executor: 'constant-arrival-rate',
      rate: 100,             // 100 iterations/sec
      timeUnit: '1s',
      duration: '5m',
      preAllocatedVUs: 50,
      maxVUs: 200,
    },
    // Per-VU iterations
    per_vu: {
      executor: 'per-vu-iterations',
      vus: 10,
      iterations: 100,
    },
  },
};

Test Types

测试类型

See
references/test-types.md
for full examples.
TypePurposeLoad Pattern
SmokeVerify script works, minimal load1-2 VUs, short duration
LoadNormal expected loadRamp up → steady → ramp down
StressBeyond normal capacityIncreasing stages until breaking
SpikeSudden traffic surgeInstant spike then drop
SoakExtended duration for memory leaksModerate load, hours-long
BreakpointFind system limitsContinuously increasing load
完整示例请查看
references/test-types.md
类型用途负载模式
冒烟测试验证脚本可用,最小负载1-2个VU,短时长
负载测试模拟正常预期负载逐步上升 → 稳定 → 逐步下降
压力测试超出正常容量的极限测试逐步增加负载直至系统崩溃
突增测试模拟突发流量激增瞬间达到峰值后回落
浸泡测试长时间运行检测内存泄漏中等负载,持续数小时
断点测试寻找系统极限持续增加负载

Environment Variables and CLI Flags

环境变量与CLI参数

bash
undefined
bash
undefined

Pass variables to script

Pass variables to script

k6 run -e MY_VAR=value script.js # access as __ENV.MY_VAR k6 run --env API_URL=https://api.example.com script.js
k6 run -e MY_VAR=value script.js # access as __ENV.MY_VAR k6 run --env API_URL=https://api.example.com script.js

Override options

Override options

k6 run --vus 50 --duration 60s script.js k6 run --iterations 1000 script.js k6 run --stage 30s:10,1m:50,30s:0 script.js # ramping stages
k6 run --vus 50 --duration 60s script.js k6 run --iterations 1000 script.js k6 run --stage 30s:10,1m:50,30s:0 script.js # ramping stages

Output formats

Output formats

k6 run --out json=result.json script.js k6 run --out csv=result.csv script.js k6 run --out influxdb=http://localhost:8086/k6 script.js k6 run --out statsd script.js
undefined
k6 run --out json=result.json script.js k6 run --out csv=result.csv script.js k6 run --out influxdb=http://localhost:8086/k6 script.js k6 run --out statsd script.js
undefined

Groups and Tags

分组与标签

javascript
import { group } from 'k6';

export default function () {
  group('homepage', () => {
    const res = http.get('/');
    check(res, { 'status 200': (r) => r.status === 200 });
  });

  group('login flow', () => {
    group('load login page', () => {
      http.get('/login');
    });
    group('submit credentials', () => {
      http.post('/login', { user: 'test', pass: 'test' });
    });
  });
}

// Custom tags on requests
http.get(url, { tags: { name: 'homepage', version: 'v2' } });
javascript
import { group } from 'k6';

export default function () {
  group('homepage', () => {
    const res = http.get('/');
    check(res, { 'status 200': (r) => r.status === 200 });
  });

  group('login flow', () => {
    group('load login page', () => {
      http.get('/login');
    });
    group('submit credentials', () => {
      http.post('/login', { user: 'test', pass: 'test' });
    });
  });
}

// Custom tags on requests
http.get(url, { tags: { name: 'homepage', version: 'v2' } });

WebSocket

WebSocket测试

javascript
import ws from 'k6/ws';
import { check } from 'k6';

export default function () {
  const url = 'ws://echo.websocket.org';
  const res = ws.connect(url, {}, function (socket) {
    socket.on('open', () => {
      socket.send('Hello!');
      socket.setInterval(() => socket.ping(), 10000);
    });
    socket.on('message', (data) => {
      check(data, { 'message received': (d) => d.length > 0 });
    });
    socket.on('error', (e) => console.error(e.error()));
    socket.setTimeout(() => socket.close(), 30000);
  });
  check(res, { 'status 101': (r) => r.status === 101 });
}
javascript
import ws from 'k6/ws';
import { check } from 'k6';

export default function () {
  const url = 'ws://echo.websocket.org';
  const res = ws.connect(url, {}, function (socket) {
    socket.on('open', () => {
      socket.send('Hello!');
      socket.setInterval(() => socket.ping(), 10000);
    });
    socket.on('message', (data) => {
      check(data, { 'message received': (d) => d.length > 0 });
    });
    socket.on('error', (e) => console.error(e.error()));
    socket.setTimeout(() => socket.close(), 30000);
  });
  check(res, { 'status 101': (r) => r.status === 101 });
}

Browser Testing

浏览器测试

javascript
import { browser } from 'k6/browser';
import { check } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js';

export const options = {
  scenarios: {
    ui: {
      executor: 'shared-iterations',
      options: { browser: { type: 'chromium' } },
    },
  },
};

export default async function () {
  const page = await browser.newPage();
  try {
    await page.goto('https://test.k6.io/my_messages.php');
    await page.locator('input[name="login"]').type('admin');
    await page.locator('input[name="password"]').type('123');
    await Promise.all([
      page.waitForNavigation(),
      page.locator('input[type="submit"]').click(),
    ]);
    check(page, { 'header': p => p.locator('h2').textContent() == 'Welcome, admin!' });
  } finally {
    await page.close();
  }
}
javascript
import { browser } from 'k6/browser';
import { check } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js';

export const options = {
  scenarios: {
    ui: {
      executor: 'shared-iterations',
      options: { browser: { type: 'chromium' } },
    },
  },
};

export default async function () {
  const page = await browser.newPage();
  try {
    await page.goto('https://test.k6.io/my_messages.php');
    await page.locator('input[name="login"]').type('admin');
    await page.locator('input[name="password"]').type('123');
    await Promise.all([
      page.waitForNavigation(),
      page.locator('input[type="submit"]').click(),
    ]);
    check(page, { 'header': p => p.locator('h2').textContent() == 'Welcome, admin!' });
  } finally {
    await page.close();
  }
}

Modules and Imports

模块与导入

javascript
// Built-in modules
import http from 'k6/http';
import { check, group, sleep, fail } from 'k6';
import { Counter, Gauge, Rate, Trend } from 'k6/metrics';
import { SharedArray } from 'k6/data';
import { scenario, vu } from 'k6/execution';
import ws from 'k6/ws';
import grpc from 'k6/net/grpc';
import { browser } from 'k6/browser';
import crypto from 'k6/crypto';
import encoding from 'k6/encoding';
import { htmlReport } from 'https://raw.githubusercontent.com/benc-uk/k6-reporter/main/dist/bundle.js';

// jslib utilities
import { uuidv4 } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js';
import { randomItem, randomIntBetween } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js';
javascript
// Built-in modules
import http from 'k6/http';
import { check, group, sleep, fail } from 'k6';
import { Counter, Gauge, Rate, Trend } from 'k6/metrics';
import { SharedArray } from 'k6/data';
import { scenario, vu } from 'k6/execution';
import ws from 'k6/ws';
import grpc from 'k6/net/grpc';
import { browser } from 'k6/browser';
import crypto from 'k6/crypto';
import encoding from 'k6/encoding';
import { htmlReport } from 'https://raw.githubusercontent.com/benc-uk/k6-reporter/main/dist/bundle.js';

// jslib utilities
import { uuidv4 } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js';
import { randomItem, randomIntBetween } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js';

SharedArray (efficient data loading)

SharedArray(高效数据加载)

javascript
import { SharedArray } from 'k6/data';
import papaparse from 'https://jslib.k6.io/papaparse/5.1.1/index.js';

// Load CSV once, shared across all VUs
const users = new SharedArray('users', function () {
  return papaparse.parse(open('./users.csv'), { header: true }).data;
});

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

export default function () {
  const user = users[Math.floor(Math.random() * users.length)];
  http.post('/login', { username: user.username, password: user.password });
}
javascript
import { SharedArray } from 'k6/data';
import papaparse from 'https://jslib.k6.io/papaparse/5.1.1/index.js';

// Load CSV once, shared across all VUs
const users = new SharedArray('users', function () {
  return papaparse.parse(open('./users.csv'), { header: true }).data;
});

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

export default function () {
  const user = users[Math.floor(Math.random() * users.length)];
  http.post('/login', { username: user.username, password: user.password });
}

k6 Cloud (Grafana Cloud k6)

k6 Cloud(Grafana Cloud k6)

javascript
export const options = {
  cloud: {
    projectID: 123456,
    name: 'My Load Test',
    note: 'Release candidate',
    distribution: {
      distributionLabel1: { loadZone: 'amazon:us:ashburn', percent: 50 },
      distributionLabel2: { loadZone: 'amazon:eu:dublin', percent: 50 },
    },
  },
};
bash
undefined
javascript
export const options = {
  cloud: {
    projectID: 123456,
    name: 'My Load Test',
    note: 'Release candidate',
    distribution: {
      distributionLabel1: { loadZone: 'amazon:us:ashburn', percent: 50 },
      distributionLabel2: { loadZone: 'amazon:eu:dublin', percent: 50 },
    },
  },
};
bash
undefined

Authenticate

Authenticate

k6 cloud login --token <your-token>
k6 cloud login --token <your-token>

Run in cloud

Run in cloud

k6 cloud script.js
k6 cloud script.js

Run locally but stream results to cloud

Run locally but stream results to cloud

k6 run --out cloud script.js
undefined
k6 run --out cloud script.js
undefined

CLI Flags Summary

CLI参数汇总

FlagDescription
--vus N
Number of virtual users
--duration Xs/Xm/Xh
Test duration
--iterations N
Total iterations
--stage Xm:N
Add ramp stage
--env KEY=value
Environment variable
--out FORMAT
Output destination
--quiet
Suppress progress output
--no-summary
Skip end-of-test summary
--summary-export FILE
Export summary as JSON
--http-debug
Print HTTP request/response details
--insecure-skip-tls-verify
Skip TLS verification
--tag KEY=VALUE
Add test-wide tag
参数描述
--vus N
虚拟用户数量
--duration Xs/Xm/Xh
测试时长
--iterations N
总迭代次数
--stage Xm:N
添加负载梯度阶段
--env KEY=value
设置环境变量
--out FORMAT
输出目标格式
--quiet
抑制进度输出
--no-summary
跳过测试结束总结
--summary-export FILE
导出总结为JSON格式
--http-debug
打印HTTP请求/响应详情
--insecure-skip-tls-verify
跳过TLS验证
--tag KEY=VALUE
添加测试全局标签

Key Built-in Metrics

核心内置指标

MetricTypeDescription
http_req_duration
TrendTotal request time
http_req_failed
RateFailed request rate
http_req_waiting
TrendTime to first byte (TTFB)
http_req_connecting
TrendTCP connection time
http_req_tls_handshaking
TrendTLS handshake time
http_reqs
CounterTotal HTTP requests
vus
GaugeCurrent active VUs
vus_max
GaugeMax VUs allocated
iterations
CounterTotal VU iterations
iteration_duration
TrendTime to complete one iteration
data_sent
CounterData sent
data_received
CounterData received
checks
RateCheck success rate
指标类型描述
http_req_duration
趋势指标请求总时长
http_req_failed
比率指标请求失败率
http_req_waiting
趋势指标首字节时间(TTFB)
http_req_connecting
趋势指标TCP连接时间
http_req_tls_handshaking
趋势指标TLS握手时间
http_reqs
计数器HTTP请求总数
vus
仪表盘指标当前活跃虚拟用户数
vus_max
仪表盘指标分配的最大虚拟用户数
iterations
计数器虚拟用户总迭代次数
iteration_duration
趋势指标单次迭代完成时间
data_sent
计数器发送的数据量
data_received
计数器接收的数据量
checks
比率指标检查成功率

References

参考资料

  • JavaScript API
  • Test Types
  • Scenarios & Executors
  • Examples
  • JavaScript API
  • 测试类型
  • 场景与执行器
  • 示例