Wener Notes

k6

约 5 分钟阅读
bash
brew install k6
# https://github.com/grafana/k6/releases
curl -LO https://github.com/grafana/k6/releases/download/v0.45.0/k6-v0.45.0-linux-amd64.tar.gz
tar zxvf k6-v0.45.0-linux-amd64.tar.gz --strip-components 1
./k6

k6 run script.js
JavaScript
import { check, sleep } from 'k6';
import http from 'k6/http';

// 选项
export const options = {
  // 单个
  vus: 10, // 虚拟用户数
  duration: '30s', // 基于时间
  iterations: 100, // 基于迭代
  // or 多个场景
  // stages: [
  //   { duration: '30s', target: 20 },
  //   { duration: '1m30s', target: 10 },
  //   { duration: '20s', target: 0 },
  // ],
  // 目标,SLO
  thresholds: {
    // Assert that 99% of requests finish within 3000ms.
    http_req_duration: ['p(99) < 3000'],
  },
};

// vu 测试
export default function () {
  const res = http.get('https://wener.me');
  check(res, { 'status was 200': (r) => r.status == 200 });
  sleep(1);
}
  • virtual users (VUs)
  • __ENV
  • __VU
  • __ITER
  • warmup 放在 scenario
JavaScript
// 1. init code - 每个 UV 调用 1 次

export function setup() {
  // 2. setup code - 全局只会调用 1 次
  return {};
}

// data 为 setup 返回结果
export default function (data) {
  // 3. VU code - 每次迭代调用 1 次
}

// data 为 setup 返回结果
export function teardown(data) {
  // 4. teardown code - 全局调用 1 次,如果 setup 失败则不调用
}

// 通过配置 scenarios.*.exec 来指定执行
export function webtest() {}
  • handleSummary
k6 run flagsfor
-u,--vus INT默认 1, 虚拟用户数
-d,--duration DURATION持续时间
-i,--iterations INT迭代次数
-s,--stage STAGE[duration]:[target]
--rps INT限制每秒请求数
--http-debug默认 headers, dump http request
--http-debug=full包含 body

Dashboard

bash
K6_WEB_DASHBOARD=true K6_WEB_DASHBOARD_EXPORT=summary.html

K6_WEB_DASHBOARD_HOST=localhost
K6_WEB_DASHBOARD_PORT=5665
K6_WEB_DASHBOARD_PERIOD=10s
K6_WEB_DASHBOARD_OPEN=false

notes

  • executor 执行器
    • shared-iterations - 迭代次数在所有 VU (虚拟用户) 之间共享
    • per-vu-iterations - 每个 VU 执行固定次数的迭代
    • constant-vus - 在指定时间内,使用固定数量的 VU 持续执行尽可能多的迭代
    • ramping-vus - 在测试期间,VU 数量会逐渐增加或减少
    • constant-arrival-rate - 以恒定的速率开始新的迭代
    • ramping-arrival-rate - 新迭代的速率会逐渐增加或减少
    • externally-controlled - 通过外部触发器来控制测试的执行

context

  • instance
  • scenario
  • vu
JavaScript
import exec from 'k6/execution';

export default function () {
  console.log(`Execution context

Instance info
-------------
Vus active: ${exec.instance.vusActive}
Iterations completed: ${exec.instance.iterationsCompleted}
Iterations interrupted:  ${exec.instance.iterationsInterrupted}
Iterations completed:  ${exec.instance.iterationsCompleted}
Iterations active:  ${exec.instance.vusActive}
Initialized vus:  ${exec.instance.vusInitialized}
Time passed from start of run(ms):  ${exec.instance.currentTestRunDuration}

Scenario info
-------------
Name of the running scenario: ${exec.scenario.name}
Executor type: ${exec.scenario.executor}
Scenario start timestamp: ${exec.scenario.startTime}
Percenatage complete: ${exec.scenario.progress}
Iteration in instance: ${exec.scenario.iterationInInstance}
Iteration in test: ${exec.scenario.iterationInTest}

Test info
---------
All test options: ${exec.test.options}

VU info
-------
Iteration id: ${exec.vu.iterationInInstance}
Iteration in scenario: ${exec.vu.iterationInScenario}
VU ID in instance: ${exec.vu.idInInstance}
VU ID in test: ${exec.vu.idInTest}
VU tags: ${exec.vu.tags}`);
}

xk6

bash
go install go.k6.io/xk6/cmd/xk6@latest

xk6 build --with github.com/grafana/xk6-output-timescaledb --with github.com/szkiba/xk6-dotenv@latest
xk6 build --with github.com/phymbert/xk6-sse@latest --with github.com/szkiba/xk6-dotenv@latest
./k6

# -o $K6_OUT
K6_OUT=timescaledb=postgresql://k6:k6@timescaledb:5432/k6 k6 run script.js

timescaledb

  • samples
  • thresholds
  • K6_TIMESCALEDB_PUSH_INTERVAL=1s
    • 2min 约 500 万 条记录、2G
    • 越长使用越多内存
bash
k6 run --tag testid=SVR-$(date +%Y%m%d-%H%M)
sql
CREATE TABLE IF NOT EXISTS samples (
  ts timestamptz NOT NULL DEFAULT current_timestamp,
  metric varchar(128) NOT NULL,
  tags jsonb,
  value real
);
CREATE TABLE IF NOT EXISTS thresholds (
  id serial,
  ts timestamptz NOT NULL DEFAULT current_timestamp,
  metric varchar(128) NOT NULL,
  tags jsonb,
  threshold varchar(128) NOT NULL,
  abort_on_fail boolean DEFAULT FALSE,
  delay_abort_eval varchar(128),
  last_failed boolean DEFAULT FALSE
);
SELECT create_hypertable('samples', 'ts');
CREATE INDEX IF NOT EXISTS idx_samples_ts ON samples (ts DESC);
CREATE INDEX IF NOT EXISTS idx_thresholds_ts ON thresholds (ts DESC);

-- 可以考虑
create index samples_ts_tags_testid on samples using btree (ts, ((tags ->> 'testid'::text)));

SQL

Setup

bash
sudo apk add go
sudo chown $USER mkdir -p /data

mkdir -p /data/bin
go env -w GOPROXY=https://goproxy.cn,direct

go install go.k6.io/xk6/cmd/xk6@latest
GOBIN=/data/bin go install go.k6.io/xk6/cmd/xk6@latest

export PATH="/data/bin:$PATH"

# CGO_ENABLED=1 for SQLite
# --output /data/bin
xk6 build \
  --with github.com/grafana/xk6-output-timescaledb \
  --with github.com/szkiba/xk6-dotenv \
  --with github.com/szkiba/xk6-dashboard \
  --with github.com/avitalique/xk6-file \
  --with github.com/szkiba/xk6-top \
  --with github.com/grafana/xk6-sql

mv k6 /data/bin/
mkdir -p /data/k6
cd /data/k6

Target RPS

JavaScript
export const options = {
  scenarios: {
    constant_request_rate: {
      executor: 'constant-arrival-rate',
      rate: 1,
      timeUnit: '1s',
      duration: '1m',
      preAllocatedVUs: 20,
      maxVUs: 100,
    },
    stageOne: {
      executor: 'constant-arrival-rate',
      duration: '5m',
      rate: 1000000, // 1mil QPS for 5 min
      timeUnit: '1s',
      maxVUs: 12500, // Some number with headroom where I try to judge, given some hypothetical SUT latency, how I can reach 1mil QPS?
    },
    stageTwo: {
      executor: 'constant-arrival-rate',
      duration: '5m',
      startTime: '5m',
      rate: 10000000, // 10mil QPS for 5 min
      timeUnit: '1s',
      maxVUs: 125000, // Ditto
    },
    // ...
  },
};

gracefulStop

关联信息

反向链接、本文链接的其他页面和外部资料。

References

GitHub15 条
其他外链6 条
最近更新commit 2df24bdEdit

On this page