我的测试学习站TEST LEARNING HUB
开始学习
首页/我的面试题/如何结合 k6 进行性能测试

如何结合 k6 进行性能测试

k6 是什么

k6 是 Grafana 开源的性能测试工具,特点:

  • 用 JavaScript/TypeScript 写脚本。
  • CLI 执行,适合 CI。
  • 支持多种压测场景:固定并发、阶梯加压、固定到达率、峰值、浸泡。
  • 内置阈值(thresholds)、检查(checks)和指标。
  • 可输出 JSON、CSV、Prometheus、Grafana Cloud 等。

适合:接口压测、微服务容量评估、CI 性能门禁、持续性能测试。

安装和运行

# Windows: winget install k6 --source winget
# macOS: brew install k6
# 或直接下载二进制

k6 run script.js
k6 run --vus 50 --duration 5m script.js

脚本结构

import http from 'k6/http'
import { check, sleep } from 'k6'
import { Trend, Rate } from 'k6/metrics'

const loginDuration = new Trend('login_duration')
const orderFailRate = new Rate('order_fail_rate')

export const options = {
  scenarios: {
    smoke: {
      executor: 'constant-vus',
      vus: 5,
      duration: '1m',
      tags: { test_type: 'smoke' },
    },
    load: {
      executor: 'ramping-vus',
      startVUs: 0,
      stages: [
        { duration: '2m', target: 50 },
        { duration: '5m', target: 50 },
        { duration: '2m', target: 0 },
      ],
      startTime: '1m',
      tags: { test_type: 'load' },
    },
  },
  thresholds: {
    http_req_duration: ['p(95)<500', 'p(99)<1000'],
    http_req_failed: ['rate<0.01'],
    'http_req_duration{test_type:load}': ['p(95)<800'],
  },
}

export default function () {
  const loginRes = http.post(`${__ENV.BASE_URL}/api/login`, JSON.stringify({
    username: __ENV.USER,
    password: __ENV.PASSWORD,
  }), { headers: { 'Content-Type': 'application/json' } })

  loginDuration.add(loginRes.timings.duration)
  check(loginRes, {
    'login 200': (r) => r.status === 200,
    'has token': (r) => !!r.json('token'),
  })

  const token = loginRes.json('token')
  const headers = { Authorization: `Bearer ${token}` }

  const products = http.get(`${__ENV.BASE_URL}/api/products`, { headers })
  check(products, { 'products 200': (r) => r.status === 200 })

  const order = http.post(`${__ENV.BASE_URL}/api/orders`, JSON.stringify({
    productId: 101,
    quantity: 1,
  }), { headers: { ...headers, 'Content-Type': 'application/json' } })

  orderFailRate.add(order.status >= 400)
  check(order, {
    'order 200': (r) => r.status === 200,
    'order has id': (r) => !!r.json('order.id'),
  })

  sleep(1)
}

场景类型

场景executor适用
冒烟constant-vus验证脚本和基本链路
负载ramping-vus模拟逐步加压和稳态
固定到达率constant-arrival-rate精确控制 RPS
阶梯到达率ramping-arrival-rate找拐点、测容量
峰值ramping-arrival-rate短时突发
浸泡constant-vus + 长时间内存泄漏、连接泄漏
按迭代per-vu-iterations / shared-iterations固定次数

工作负载建模

压测不是“把 VU 拉满”,而是模拟真实业务:

  • 业务比例:登录、浏览、加购、下单、支付各占多少。
  • 思考时间:用 sleep 模拟用户间隔。
  • 数据分布:热门商品和冷门商品比例。
  • 峰值模型:日常、活动、大促的流量曲线。
  • 持续时间:短时峰值和长时间浸泡都要覆盖。
  • 环境隔离:压测环境独立,避免影响测试数据和其他人。

数据和关联

  • 用 SharedArray 加载 CSV/JSON,避免每个 VU 复制大对象。
  • 每个 VU 使用唯一用户和数据,避免锁竞争和重复数据。
  • 从登录响应提取 token,从创建订单响应提取 orderId。
  • 用 http.batch 并行请求,模拟页面并发加载。
  • 需要签名时,在脚本里实现签名函数,注意时间戳和 nonce。

阈值和检查

  • checks:断言单次请求结果,失败会计入指标。
  • thresholds:定义通过/失败标准,CI 中可直接阻断。
  • 常用阈值:
    • http_req_duration: ['p(95)<500']
    • http_req_failed: ['rate<0.01']
    • 自定义指标,如 order_fail_rate: ['rate<0.001']

结果输出

k6 run --out json=result.json script.js
k6 run --out csv=result.csv script.js
  • 本地分析:JSON/CSV。
  • 实时监控:Prometheus remote write + Grafana。
  • 云端:Grafana Cloud k6。
  • CI:阈值失败返回非零退出码,阻断流水线。

分布式压测

单机压测容易受客户端 CPU、网络和端口限制。流量大时:

  • 多台压测机分片。
  • Kubernetes 上用 k6 Operator。
  • 压测机和服务端分开,避免互相影响。
  • 监控压测机自身的 CPU、网络和连接数。

最佳实践

  • 先冒烟,再负载,再峰值/浸泡。
  • 每次只改变一个变量,便于对比。
  • 记录版本、配置、数据量和环境。
  • 同时监控服务端、数据库、缓存、MQ 和网络。
  • 压测数据要清理或使用独立环境。
  • 把核心接口的性能阈值接入 CI,防止性能回退。

反模式

  • 只压一个接口,忽略业务链路。
  • 所有 VU 共用同一个账号,产生锁竞争。
  • 压测机和服务端在同一台机器。
  • 只看平均值,不看 p95/p99。
  • 没有基线,无法判断变好还是变坏。
  • 压测后不清理数据,污染环境。

面试回答模板

我会用 k6 写接口压测脚本,按冒烟、负载、峰值和浸泡设计场景,用 ramping-vus 或 arrival-rate 模拟真实流量。脚本里做登录 token 关联、唯一数据、业务比例和思考时间,设置 p95/p99 和错误率阈值,接入 CI 做性能门禁。结果输出到 JSON/Prometheus,同时监控服务端、数据库和缓存,最后结合服务端指标定位瓶颈。