k6 场景:组织与选择工作负载

Open source

场景可以细致配置虚拟用户(VU)与迭代调度。借助场景,可以在负载测试中建立不同工作负载或流量模式。

使用场景的好处包括:

  • 测试组织更简单灵活:同一脚本可声明多个场景,每个场景独立执行不同的 JavaScript 函数。
  • 模拟更真实的流量:每个场景可以通过专用执行器,采用不同的虚拟用户和迭代调度模式。 executor
  • 并行或顺序工作负载:场景彼此独立,默认并行运行;精细设置各场景的 startTime,可以使它们表现为顺序执行。
  • 细粒度结果分析:每个场景可分别配置环境变量和指标标签。

配置场景

在 options 对象中使用 scenarios 键配置场景。名称可以自行决定,只要在脚本中唯一即可。

场景名称会出现在结果摘要、标签等位置。

JavaScript

export const options = {
  scenarios: {
    example_scenario: {
      // name of the executor to use
      executor: 'shared-iterations',

      // common scenario configuration
      startTime: '10s',
      gracefulStop: '5s',
      env: { EXAMPLEVAR: 'testing' },
      tags: { example_tag: 'testing' },

      // executor-specific configuration
      vus: 10,
      iterations: 200,
      maxDuration: '10s',
    },
    another_scenario: {
      /*...*/
    },
  },
};

场景执行器

每个 k6 场景的虚拟用户工作负载都由执行器调度。执行器决定测试持续多久、流量恒定还是变化,以及按虚拟用户还是到达率建立负载模型,即闭合模型或开放模型。 open or closed models

场景对象必须在 executor 属性中指定一个预定义执行器名称。执行器决定 k6 如何建立负载,选项包括:

  • 按迭代次数。

  • 按虚拟用户数量。

    • constant-VUs:保持固定虚拟用户数量。 constant-VUs
    • ramping-vus:按配置阶段调整虚拟用户数量。 ramping-vus
  • 按迭代速率。

除了通用场景选项,每种执行器还提供与其工作负载相关的专有选项。完整列表见执行器文档。 Executors

场景选项

选项 类型 说明 默认值
executor(必填) 字符串 唯一的执行器名称。允许值见执行器章节。 executors –
startTime 字符串 相对于测试开始的时间偏移;到达该时刻后开始执行本场景。 "0s"
gracefulStop 字符串 强制停止迭代之前,等待迭代完成的时间。详见优雅停止。 Graceful stop "30s"
exec 字符串 需要执行的导出 JavaScript 函数名称。 "default"
env object 该场景专用的环境变量。 {}
tags object 该场景专用的标签。 Tags {}
options object 附加选项,包括浏览器选项。 browser options {}

场景示例

这个脚本组合了两个场景,并设置先后启动时间:

  • shared_iter_scenario 立即开始。10个虚拟用户尽快完成总计100次迭代;某些用户可能比其他用户执行更多次。
  • per_vu_scenario 在10秒后开始。10个虚拟用户各执行10次迭代。

哪个场景耗时更长?可以运行后观察,也可以为其中一个或两个场景添加 maxDuration。

JavaScript

import http from 'k6/http';

export const options = {
  scenarios: {
    shared_iter_scenario: {
      executor: 'shared-iterations',
      vus: 10,
      iterations: 100,
      startTime: '0s',
    },
    per_vu_scenario: {
      executor: 'per-vu-iterations',
      vus: 10,
      iterations: 10,
      startTime: '10s',
    },
  },
};

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

运行含有场景的脚本时,k6 输出会包含每个场景的概况。例如执行 k6 run scenario-example.js 后,会按如下方式报告场景:

Bash

  execution: local
     script: scenario-example.js
     output: -

  scenarios: (100.00%) 2 scenarios, 20 max VUs, 10m40s max duration (incl. grace
ful stop):
           * shared_iter_scenario: 100 iterations shared among 10 VUs (maxDurati
on: 10m0s, gracefulStop: 30s)
           * per_vu_scenario: 10 iterations for each of 10 VUs (maxDuration: 10m
0s, startTime: 10s, gracefulStop: 30s)

完整输出还包含汇总指标,与默认的测试结束摘要相同:

Bash

         /\      Grafana   /‾‾/
    /\  /  \     |\  __   /  /
   /  \/    \    | |/ /  /   ‾‾\
  /          \   |   (  |  (‾)  |
 / __________ \  |_|\_\  \_____/

  execution: local
     script: scenario-example.js
     output: -

  scenarios: (100.00%) 2 scenarios, 20 max VUs, 10m40s max duration (incl. grace
ful stop):
           * shared_iter_scenario: 100 iterations shared among 10 VUs (maxDurati
on: 10m0s, gracefulStop: 30s)
           * per_vu_scenario: 10 iterations for each of 10 VUs (maxDuration: 10m
0s, startTime: 10s, gracefulStop: 30s)

  █ TOTAL RESULTS

    HTTP
    http_req_blocked........................................................: avg=24.59ms  min=1µs      med=4µs      max=263.64ms p(90)=22.48ms  p(95)=245.04ms
    http_req_connecting.....................................................: avg=11.36ms  min=0s       med=0s       max=120.45ms p(90)=10.76ms  p(95)=115.19ms
    http_req_duration.......................................................: avg=115.25ms min=108.25ms med=115.66ms max=170.62ms p(90)=119.59ms p(95)=121.13ms
      { expected_response:true }............................................: avg=115.25ms min=108.25ms med=115.66ms max=170.62ms p(90)=119.59ms p(95)=121.13ms
    http_req_failed.........................................................: 0.00%  0 out of 200
    http_req_receiving......................................................: avg=214.61µs min=15µs     med=73.5µs   max=4.57ms   p(90)=253.4µs  p(95)=1.08ms
    http_req_sending........................................................: avg=17.79µs  min=3µs      med=12µs     max=669µs    p(90)=22µs     p(95)=25µs
    http_req_tls_handshaking................................................: avg=12.01ms  min=0s       med=0s       max=126.23ms p(90)=11.49ms  p(95)=120.04ms
    http_req_waiting........................................................: avg=115.02ms min=107.7ms  med=115.33ms max=170.59ms p(90)=119.54ms p(95)=121.04ms
    http_reqs...............................................................: 200    17.489795/s

    EXECUTION
    iteration_duration......................................................: avg=140.07ms min=108.3ms  med=116.14ms max=383.32ms p(90)=187.14ms p(95)=363.64ms
    iterations..............................................................: 200    17.489795/s
    vus.....................................................................: 10     min=0        max=10
    vus_max.................................................................: 20     min=20       max=20

    NETWORK
    data_received...........................................................: 2.4 MB 209 kB/s
    data_sent...............................................................: 26 kB  2.3 kB/s


  █ SCENARIO: per_vu_scenario

    HTTP
    http_req_blocked...................................: avg=23.52ms  min=1µs      med=4µs      max=244.87ms p(90)=22.39ms  p(95)=234.84ms
    http_req_connecting................................: avg=11.45ms  min=0s       med=0s       max=120.45ms p(90)=10.84ms  p(95)=115.81ms
    http_req_duration..................................: avg=114.86ms min=108.25ms med=115.74ms max=123.17ms p(90)=120.08ms p(95)=121.13ms
    http_req_failed....................................: 0.00%  0 out of 100
    http_req_receiving.................................: avg=195.59µs min=15µs     med=73.5µs   max=4.57ms   p(90)=247.5µs  p(95)=875.99µs
    http_req_sending...................................: avg=20.8µs   min=3µs      med=12µs     max=669µs    p(90)=22.1µs   p(95)=27.09µs
    http_req_tls_handshaking...........................: avg=12.06ms  min=0s       med=0s       max=126.23ms p(90)=11.49ms  p(95)=120.61ms
    http_req_waiting...................................: avg=114.64ms min=107.78ms med=115.38ms max=123.07ms p(90)=120.04ms p(95)=121.04ms
    http_reqs..........................................: 100    8.744897/s

    EXECUTION
    iteration_duration.................................: avg=138.53ms min=108.3ms  med=116.22ms max=363.71ms p(90)=144.44ms p(95)=353.48ms
    iterations.........................................: 100    8.744897/s

    NETWORK
    data_received......................................: 1.2 MB 104 kB/s
    data_sent..........................................: 13 kB  1.1 kB/s


  █ SCENARIO: shared_iter_scenario

    HTTP
    http_req_blocked...................................: avg=25.66ms  min=1µs      med=4µs      max=263.64ms p(90)=24.98ms  p(95)=256.16ms
    http_req_connecting................................: avg=11.27ms  min=0s       med=0s       max=115.37ms p(90)=10.76ms  p(95)=115.15ms
    http_req_duration..................................: avg=115.65ms min=108.38ms med=115.61ms max=170.62ms p(90)=119.11ms p(95)=120.91ms
    http_req_failed....................................: 0.00%  0 out of 100
    http_req_receiving.................................: avg=233.63µs min=22µs     med=73.5µs   max=4.22ms   p(90)=324.6µs  p(95)=1.11ms
    http_req_sending...................................: avg=14.77µs  min=3µs      med=12µs     max=128µs    p(90)=20µs     p(95)=22µs
    http_req_tls_handshaking...........................: avg=11.96ms  min=0s       med=0s       max=124.34ms p(90)=11.64ms  p(95)=118.98ms
    http_req_waiting...................................: avg=115.4ms  min=107.7ms  med=115.33ms max=170.59ms p(90)=118.94ms p(95)=120.85ms
    http_reqs..........................................: 100    8.744897/s

    EXECUTION
    iteration_duration.................................: avg=141.6ms  min=108.46ms med=116.09ms max=383.32ms p(90)=189.98ms p(95)=375.24ms
    iterations.........................................: 100    8.744897/s

    NETWORK
    data_received......................................: 1.2 MB 104 kB/s
    data_sent..........................................: 13 kB  1.1 kB/s

running (00m12.8s), 00/20 VUs, 200 complete and 0 interrupted iterations
shared_iter_scenario ✓ [ 100% ] 10 VUs  00m02.7s/10m0s  100/100 shared iters
per_vu_scenario      ✓ [ 100% ] 10 VUs  00m02.8s/10m0s  100/100 iters, 10 per V

运行选定场景

使用 –scenario 可以运行多场景脚本中的一部分,无需修改脚本或额外增加环境变量逻辑。例如,只运行正在开发的 API 方法对应的负载,或每次提交运行子集、较低频率运行全量测试。选中场景保留原本配置的负载。 –scenario

将下面示例保存为 scenarios.js:

JavaScript

export const options = {
  scenarios: {
    api: {
      executor: 'shared-iterations',
      vus: 1,
      iterations: 2,
      exec: 'api',
    },
    checkout: {
      executor: 'shared-iterations',
      vus: 1,
      iterations: 3,
      exec: 'checkout',
    },
  },
  thresholds: {
    iterations: ['count>0'],
    'iterations{scenario:api}': ['count>0'],
    'iterations{scenario:checkout}': ['count>0'],
  },
};

export function api() {
  console.log('API iteration');
}

export function checkout() {
  console.log('Checkout iteration');
}

选择一个名称,或用逗号分隔多个名称:

sh

k6 run --scenario checkout scenarios.js
k6 run --scenario api,checkout scenarios.js

第一条命令执行3次 checkout 迭代,第二条按各自配置的迭代次数运行两个场景。选择操作保留各场景的执行器、负载、时间设置、函数、环境变量、标签和浏览器设置。其他全局选项和正常测试生命周期仍然适用,包括 setup() 和 teardown()。

脚本初始化完成后,名称必须存在于配置的 scenarios 对象中。仅有 default 导出不会定义可选择的场景;–scenario default 要求明确配置 scenarios.default。空选择或未知名称会返回错误。

负载选项与阈值

–scenario 不能与 –vus、–duration、–iterations 或 –stage 同时使用。k6 会忽略脚本、配置文件或环境变量中对应的顶层设置,并输出警告;选中场景内部设置保持不变。执行分段仍然有效,可能减少选中场景实际分配到的工作量。

如果某个阈值的 scenario 标签指定了已配置但被排除的场景,选择操作会删除该阈值并输出警告。例如只选择 checkout 时,会跳过 API 阈值,保留全局和 checkout 阈值。全局阈值、不含 scenario 标签的过滤条件,以及指定选中场景或未配置场景的过滤条件仍有效。因此,预期完整工作负载的全局计数阈值仍可能使部分运行失败。

即使其他场景生成带有被排除场景标签的样本,被跳过的阈值也不会重新启用。例如选中的 checkout 场景产生 scenario:api 标签的自定义指标时,被选择操作移除的 API 阈值不会评估这些样本。决定哪些断言应该共享时,参见特定标签阈值文档。 thresholds for specific tags

云端运行与归档

相同选择方式适用于 k6 cloud run,包括 –local-execution,以及 k6 archive。归档保存选中的场景和剩余阈值,因此重放归档时无需再次指定 –scenario。重放时省略该参数,不会恢复被排除的场景或阈值。

每个选中场景运行一次

要用单次迭代检查选中工作负载,可以组合 –scenario 与 –once。前者选择场景,后者为每个场景配置一个虚拟用户、一次迭代:

sh

k6 run --scenario api,checkout --once scenarios.js

这条命令分别执行一次 API 和 checkout 迭代。各场景保留函数、环境、标签和浏览器设置;–once 将执行器与时间设置重置为 shared-iterations、startTime: ‘0s’、maxDuration: ’10m’、gracefulStop: ’30s’。执行分段不能与 –once 一起使用。仅传 –once 仍会拒绝多场景脚本;显式选择告诉 k6 应运行哪些场景。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容