k6:现代性能测试工具的新标杆

张开发
2026/4/4 14:17:49 15 分钟阅读
k6:现代性能测试工具的新标杆
本人已经有几年不接触性能测试了近些年一直是在从事功能和操作系统的自动化测试工作现在回头看以前所专注的性能测试工具感觉是有点跟不上时代了在网上无意中发现一款比较火的工具k6我也不知道这工具是哪年冒出来的但是初步了解了下发现这工具非常符合新时代的标准在AI时代更能发挥其作用和价值。传统的性能测试工具如JMeter和Locust虽然功能强大但随着云原生和微服务架构特别是AI智能体时代的普及它们逐渐暴露出一些局限性。而Grafana k6作为新一代性能测试工具凭借其独特的设计理念和技术优势正在重新定义性能测试的标准。 极致性能单机压测能力远超传统工具k6基于Go语言开发充分利用了Go的并发模型和内存管理优势在单机性能上实现了质的飞跃高并发支持单个k6实例可轻松模拟数万虚拟用户而JMeter在同等硬件条件下通常只能支持几千用户低资源消耗k6的内存占用仅为JMeter的1/10CPU使用率更加稳定高效零GC停顿Go语言的垃圾回收机制优化得当避免了Java工具常见的GC停顿问题实际测试数据显示在相同硬件配置下k6的请求吞吐量比JMeter高出3-5倍比Locust高出2-3倍真正实现了少即是多的设计哲学。 跨平台无缝迁移部署简单如二进制文件k6的跨平台特性让性能测试从未如此简单单一二进制文件充分利用Go的优势无需安装Java运行时或Python环境下载即用全平台支持完美运行于Windows、macOS、Linux包括ARM架构容器化友好官方Docker镜像仅30MB启动时间不到1秒CI/CD无缝集成与Jenkins、GitLab CI、GitHub Actions等主流工具深度集成# 下载即用无需安装 wget https://github.com/grafana/k6/releases/latest/download/k6-linux-amd64.tar.gz tar -xzf k6-linux-amd64.tar.gz ./k6 run test.js 丰富的报告展示与多维度性能指标k6不仅关注能否压测更关注如何洞察多样化报告输出控制台实时指标支持测试过程中实时显示关键性能指标通过启用 k6 的内置 Web 监控仪表板功能如下K6_WEB_DASHBOARDtrue k6 run --out jsontest_results.json test.js就可以通过默认5665登录访问而且支持报告导出如保存为html报告如下所示JSON/CSV导出便于自动化分析和处理可以集成第三方工具或方法对JSON报告数据进行处理和展示HTML报告美观的可视化报告支持自定义模板支持第三方模板如https://github.com/benc-uk/k6-reporter多种输出格式支持influxdb、Prometheus、Datadog、New Relic等和jmeter一样也支持influxdbgrafana报告输出展示但不像jmeter那样需要依赖插件配置k6是原生自带的功能直接--out将结果发送到influxdbk6 run --out influxdbhttp://localhost:8086/k6_db test.js通过grafana官网下载个模板就能调用influxdb展示报告数据全面的性能指标k6内置了丰富的性能指标无需额外插件HTTP特定指标请求持续时间、接收/发送数据量、TLS握手时间比如对一次HTTP请求的时间分解http_req_duration (总耗时)├── http_req_blocked (阻塞时间)├── http_req_connecting (连接时间)├── http_req_tls_handshaking (TLS握手时间仅HTTPS)├── http_req_sending (发送时间)├── http_req_waiting (等待时间/TTFB)└── http_req_receiving (接收时间)这一点是不是很有Loadrunner的味道在Jmeter身上没找到的东西在k6身上找到了虽然比Loadrunner还差一点点但已经足够好了系统级指标虚拟用户数、迭代次数、数据吞吐量自定义指标支持计数器、计量器、趋势分析等阈值告警实时监控性能SLA自动触发告警支持多种协议及扩展k6除了支持HTTP协议外还支持多种现代化协议主要包括1原生支持的协议HTTP/1.1​ 和HTTP/2​ - 这是k6最基础也是最常用的协议支持WebSocket​ - 支持实时双向通信的WebSocket协议测试gRPC​ - 支持高性能的gRPC远程过程调用协议Socket.io​ - 支持Socket.io实时通信框架2扩展能力k6还支持通过扩展模块如xk6扩展来增加对其他协议的支持# 安装kafka扩展 ./xk6 build --with github.com/mostafa/xk6-kafkalatest # 安装MySQL扩展 ./xk6 build --with github.com/grafana/xk6-sqllatest --with github.com/grafana/xk6-sql-driver-mysqllatest # 安装redis扩展 ./xk6 build --with github.com/grafana/xk6-redislatest以redis测试脚本调用扩展模块为例import redis from k6/x/redis; const client new redis.Client(redis://localhost:6379); export function setup() { client.set(key, value, 0); } export default async function () { // 异步获取值 const value await client.get(key); console.log(value); } 能支持基于事务和URL粒度的性能洞察k6和JMeter或Loadrunner一样都支持多层次的性能分析帮助您精准定位瓶颈事务级粒度分析import http from k6/http; import { group } from k6; export default function () { group(用户执行搜索, function () { const loginRes http.post(/api/search, { /* 搜索数据 */ }); // 事务级别的性能统计 }); group(用户访问首页, function () { // 另一个独立事务 }); }事务级指标在原生的报告里可能不展示但是可以通过json报告数据处理或是influxdb grafana模板配置进行指标结果展示URL粒度分析自动聚合相同URL的请求数据支持正则表达式匹配URL模式可针对特定API端点设置独立阈值提供P90、P95、P99等百分位响应时间等 与InfluxDBGrafana的完美生态集成k6与Grafana生态系统的无缝集成是其最大亮点之一实时数据流# 将测试结果实时写入InfluxDB k6 run --out influxdbhttp://localhost:8086/k6 test.jsGrafana可视化官方仪表板模板开箱即用的性能监控面板实时监控测试过程中动态更新图表历史对比多轮测试结果对比分析自定义查询使用InfluxQL灵活分析数据完整监控栈k6 → InfluxDB → Grafana ↓ Prometheus → AlertManager️ 分布式压测从单机到云端的无缝扩展k6支持灵活的分布式部署模式本地集群模式# 启动控制节点 k6 run --out cloud test.js # 工作节点自动加入集群 K6_CLOUD_TOKENtoken k6 agentk6 Cloud服务全球负载生成器利用Grafana Cloud的全球节点网络无需维护基础设施专注于测试脚本和结果分析弹性扩展根据需求动态调整压测规模团队协作支持多人协作和测试历史管理# 本地登录k6 Cloud非付费用户最多支持50个虚拟用户并发且仅支持同时运行一个测试 k6 login cloud --token YOUR_K6_CLOUD_API_TOKEN # 方式一本地运行结果上传云端 k6 run --out cloud script.js # 方式二直接在云端运行 k6 cloud script.jsdocker或k8s分布式测试k6支持通过Docker实现分布式负载测试以突破单机性能限制方法一使用Docker Compose部署分布式测试集群方法二Kubernetes部署使用k6 Operatorssh远程分布式压测模式如果不愿意使用k6云服务模式还能支持传统的远程控制分布式压测模式# 机器A ssh usermachine_a k6 run --vus 25 --duration 5m --execution-segment 0:1/2 --out influxdbhttp://your_influxdb_ip:8086/k6 script.js # 机器B ssh usermachine_b k6 run --vus 25 --duration 5m --execution-segment 1/2:1 --out influxdbhttp://your_influxdb_ip:8086/k6 script.js --execution-segment是负责负载分割的参数机器A的0:1/2表示执行 0% ~ 50% 的迭代机器B的1/2:1表示执行 50% ~ 100% 的迭代也就是说负载压力平均分配给两台机器如果结合后面提到的--stage参数就能灵活控制负载策略按需分配到不同机器上这个灵活性和实时控制特性是要明显优于JMeterJMeter要实现这一点要么手动修改要么依赖插件或二次开发进行虚拟线程的配置注入。--out influxdb将测试结果全部汇聚到指定influxdb这样就节省了测试报告汇聚处理的问题正常如果要对json报告进行汇聚处理难度也不会太大。测试结果汇聚最关键的一点就是两台测试机的时间一定要同步一致否则影响指标汇算。混合部署方案本地k6 云工作节点多数据中心同时压测渐进式负载增加策略⚙️ 灵活的策略配置与脚本编写k6采用JavaScript作为测试脚本语言降低了学习成本直观的负载模式配置export const options { stages: [ { duration: 2m, target: 100 }, // 2分钟爬升到100用户 { duration: 5m, target: 100 }, // 保持5分钟 { duration: 1m, target: 0 }, // 1分钟降为0 ], thresholds: { http_req_duration: [p(95)500], // 95%请求500ms http_req_failed: [rate0.01], // 失败率1% }, };还可以在脚本调用时去覆盖策略配置这样对于分布式压测就具备灵活配置的效果了如下# 覆盖虚拟用户数和持续时间 k6 run --vus 25 --duration 5m script.js # 覆盖阶段stage - 注意这会完全替换脚本中的stages k6 run --stage 1m:25,5m:25 script.js丰富的场景模拟峰值测试模拟突发流量压力测试长时间稳定压力浸泡测试持续运行发现内存泄漏容量规划阶梯式增加负载动态变压提供了专门的 externally-controlled 执行器允许通过 API 动态调整 VU 数量也支持在脚本中根据响应时间或系统时间的变化动态调整负载强度以下举例一些不同测试场景的配置方式1. 恒定虚拟用户数 (Constant VUs) 使用 constant-vus执行器保持固定数量的并发用户。 export const options { scenarios: { constant_load: { executor: constant-vus, vus: 10, // 固定10个虚拟用户 duration: 5m, // 持续5分钟 } } }; 适用场景稳定性测试、容量规划、简单的调试测试。 2. 恒定请求率 (Constant Arrival Rate) 使用 constant-arrival-rate执行器控制每秒请求数量RPS。 export const options { scenarios: { fixed_rps_test: { executor: constant-arrival-rate, rate: 50, // 每秒50个请求 timeUnit: 1s, // 时间单位 duration: 30s, // 测试持续30秒 preAllocatedVUs: 50, // 预分配VU数 maxVUs: 100, // 最大VU数 } } }; 特点开放模型无论系统响应快慢都会尝试保持固定的请求速率。 3. 阶梯式虚拟用户 (Ramping VUs) 使用 ramping-vus执行器或 stages配置模拟用户数量动态变化。 export const options { scenarios: { ramp_up: { executor: ramping-vus, startVUs: 0, stages: [ { duration: 30s, target: 50 }, // 30秒内增加到50用户 { duration: 1m, target: 50 }, // 保持50用户1分钟 { duration: 20s, target: 0 }, // 20秒内逐步降低到0 ], gracefulRampDown: 10s, // 在减少VU时给每个VU最多10秒缓冲以结束任务 } } }; 适用场景模拟真实用户访问模式早晚高峰、压力测试、容量测试。 4. 阶梯式请求率 (Ramping Arrival Rate) 使用 ramping-arrival-rate执行器模拟请求速率逐步变化。 export const options { scenarios: { ramp_rate: { executor: ramping-arrival-rate, startRate: 10, // 起始速率 timeUnit: 1s, // 时间单位 stages: [ { duration: 2m, target: 100 }, // 2分钟内增加到100 RPS { duration: 5m, target: 100 }, // 保持100 RPS { duration: 2m, target: 0 }, // 逐步降为0 ], preAllocatedVUs: 20, maxVUs: 50, } } }; 5. 共享迭代次数 (Shared Iterations) 使用 shared-iterations执行器所有虚拟用户共同完成指定次数的迭代。 export const options { scenarios: { contacts: { executor: shared-iterations, vus: 10, // 使用10个虚拟用户 iterations: 200, // 总共执行200次迭代 maxDuration: 30s, } } }; 6. 每VU迭代次数 (Per-VU Iterations) 使用 per-vu-iterations执行器每个虚拟用户执行固定次数的迭代。 export const options { scenarios: { contacts: { executor: per-vu-iterations, vus: 10, // 使用10个虚拟用户 iterations: 20, // 每个虚拟用户执行20次迭代 maxDuration: 30s, } } }; 7. 多场景混合测试 可以在一个测试中同时运行多种负载策略模拟复杂的用户行为模式。 export const options { scenarios: { // 模拟用户浏览行为 - 渐进式负载 user_browsing: { executor: ramping-vus, stages: [ { duration: 10s, target: 20 }, { duration: 50s, target: 20 }, { duration: 5s, target: 0 }, ], exec: userBrowsing, // 指定执行函数 }, // 模拟API调用 - 恒定速率 api_calls: { executor: constant-arrival-rate, rate: 100, timeUnit: 1s, duration: 60s, preAllocatedVUs: 10, exec: apiCalls, }, // 模拟批量处理 - 固定用户数 batch_processing: { executor: constant-vus, vus: 5, duration: 30s, exec: batchProcessing, }, } };现代化脚本特性ES6语法支持模块化代码组织异步/等待模式丰富的第三方库多种脚本录制和转化方式1. 官网提供Grafana k6 Studio工具可视化录制和编辑脚本或官网提供的Test BuilderGrafana Cloud k6 提供的图形界面工具实验性功能可在浏览器中配置测试场景并生成完整脚本2. har-to-k6 开源npm包用于将 HARHTTP Archive文件转换为 K6 脚本最经典的方案是用requestlyhttps://requestly.com/downloads/desktop/录制或编辑脚本导出HAR 文件再用har-to-k6 转化成K6脚本npm install --global har-to-k6 har-to-k6 your-har-file.har -o my-k6-script.js3. postman-to-k6 开源npm包用于将Postman测试脚本转化成k6脚本个人认为postman不如免费的requestly但不可否认的是postman历史悠久积累了更广泛的用户群体npm install -D postman-to-k6 npx postman-to-k6 my_collection.json -o my_k6_script.js4. openapi-to-k6 开源npm包可将OpenAPI规范转换为k6可用的TypeScript SDK需要强调的是requestly支持将APIs导出成postman脚本文件或OpenAPI文件支持JSON和YAML格式而且requestly免费开源的支持JavaScript支持浏览器或移动扩展和windows或linux桌面应用所以使用requestly编制或Swagger构建的api都可以方便转成k6脚本# 安装 npm install -g grafana/openapi-to-k6 # 基本使用 openapi-to-k6 openapi.yaml -o output/ # 指定输出格式 openapi-to-k6 openapi.yaml -o output/ --client-name MyApiClient5. 通过Swagger Codegen或OpenAPI Generator生成k6脚本除了以上方式这也是对开发人员比较友好的方式之一直接将OpenAPI接口规范文件转成k6脚本# 使用npm安装推荐 npm install openapitools/openapi-generator-cli -g # 或下载JAR文件 wget https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/7.20.0/openapi-generator-cli-7.20.0.jar -O openapi-generator-cli.jar # 查看所有支持的生成器 openapi-generator-cli list # 或 java -jar openapi-generator-cli.jar list # 查看k6生成器的配置选项 openapi-generator-cli config-help -g k6 # 基本生成命令 openapi-generator-cli generate \ -i openapi.yaml \ -g k6 \ -o ./k6-tests 支持模拟浏览器交互Grafana k6 内置浏览器测试能力基于 Chromium 与 CDP 协议支持点击、输入、页面导航等真实用户行为可采集 Web Vitals 等前端性能指标实现后端协议压测 前端浏览器测试一体化用一套脚本完成全链路性能验证。k6/browser代码样例import { browser } from k6/browser; // 浏览器模块也在此导入 // 测试配置 export const options { scenarios: { // 新增的浏览器用户体验测试场景 browser_ux: { executor: ramping-vus, stages: [ { duration: 5s, target: 3 }, // 5秒内增加到3个VU { duration: 4m50s, target: 3 }, // 保持3个VU运行4分50秒 { duration: 5s, target: 0 }, // 5秒内减少到0 ], options: { browser: { type: chromium, }, }, exec: browserTest, }, }, thresholds: { // 浏览器测试的阈值 browser_web_vital_lcp: [p(90) 5000], browser_web_vital_cls: [p(90) 0.1], } }; // 浏览器测试函数 export async function browserTest() { const page await browser.newPage(); const response await page.goto(https://www.******.com/index.php?catid29, { waitUntil: networkidle, }); check(response, { 首页加载成功: (r) r r.status() 200, }); // 页面停留或简单交互以便收集Web Vitalsa await page.waitForTimeout(2000); try { await page.locator(input[namedata\\[nindexingming\\]], input[typetext]).first().type(k6 test); await page.locator(button[namesubmit]).first().click(); } catch (error) { console.warn(可能未找到搜索元素跳过交互: ${error}); } await page.waitForTimeout(3000); // 等待可能的导航或内容加载 await page.close(); }调用脚本默认是chrome静默测试通过 CDP 协议进行WebSocket通信操作在后台完成网页加载、JS 执行、DOM 渲染与性能采集毕竟性能测试不适合弹出浏览器如果为了调试可以设置单用户浏览器弹窗观察具体的点击和操作事件./k6 run --out influxdbhttp://localhost:8086/k6 load_test_browser.js # 显示浏览器弹出效果 K6_BROWSER_HEADLESSfalse ./k6 run --out influxdbhttp://localhost:8086/k6 load_test_browser.jsWeb Vitals性能指标采集以下是通过grafana界面监控到的浏览器性能指标 支持外部动态调压实现外部控制的核心方法1.使用externally-controlled执行器推荐k6 提供了专门的externally-controlled执行器允许通过 API 动态调整 VU 数量。// script.js import http from k6/http; export const options { scenarios: { external_control: { executor: externally-controlled, // 关键配置 vus: 0, // 初始 VU 数 maxVUs: 100, // 最大允许的 VU 数 duration: 10m, // 测试总时长 }, }, }; export default function () { // 你的测试逻辑 http.get(https://test-api.k6.io/public/crocodiles/); }2.通过 REST API 动态控制启动测试时k6 会提供一个 REST API 端点用于实时调整 VU 数量。启动测试并启用 APIk6 run --out jsontest_results.json --http-debug script.js运行时动态调整# 增加 VU 到 50 curl -X POST http://localhost:6565/v1/scenarios/external_control/vus \ -H Content-Type: application/json \ -d {vus: 50} # 减少 VU 到 20 curl -X POST http://localhost:6565/v1/scenarios/external_control/vus \ -H Content-Type: application/json \ -d {vus: 20}3.使用 WebSocket 实时通信对于更复杂的控制逻辑可以使用 WebSocket 接口。// 外部控制脚本示例 const WebSocket require(ws); const ws new WebSocket(ws://localhost:6565/ws); ws.on(open, function open() { // 增加 VU ws.send(JSON.stringify({ type: updateScenario, scenario: external_control, vus: 75 })); });实时修改压测强度的几种策略策略 1基于响应时间的动态调整根据系统的实时响应时间自动调整负载强度。// 外部控制器脚本示例Node.js const axios require(axios); async function adaptiveLoadControl() { while (true) { // 1. 获取当前性能指标 const metrics await getK6Metrics(); const p95 metrics.http_req_duration.p95; // 2. 根据响应时间调整 VU let targetVUs; if (p95 200) { targetVUs Math.min(currentVUs 10, 100); // 增加负载 } else if (p95 500) { targetVUs Math.max(currentVUs - 20, 10); // 减少负载 } // 3. 发送调整指令 await axios.post(http://localhost:6565/v1/scenarios/external_control/vus, { vus: targetVUs }); await sleep(5000); // 每5秒调整一次 } }策略 2基于业务指标的阶梯调整根据业务指标如订单量、用户在线数调整压测强度。// 模拟业务高峰期的负载变化 const businessPeaks [ { time: 00:00, vus: 10 }, // 凌晨低峰 { time: 09:00, vus: 50 }, // 上班高峰 { time: 12:00, vus: 80 }, // 午间高峰 { time: 18:00, vus: 100 }, // 晚间高峰 { time: 22:00, vus: 30 }, // 夜间下降 ];策略 3故障注入与恢复测试模拟系统故障时的负载调整测试系统的弹性。// 故障注入场景 async function faultInjectionTest() { // 正常负载 await setVUs(50); await sleep(2m); // 模拟服务降级减少负载 await setVUs(20); await sleep(1m); // 恢复后逐步增加负载 await setVUs(40); await sleep(2m); await setVUs(60); }总结相较于k6的动态灵活配置压力的功能JMeter则是基于固定的线程组模型测试计划一旦启动线程数、循环次数等通常在运行时无法直接动态修改只能是利用第三方控件或是接受通过外部文件/数据库通信的复杂方案来“绕道”实现。 和AI结合的丝滑性k6基于现代技术栈不像JMeter基于1998年的Java技术栈使用Web API标准的JSON报告而且k6不再局限于传统测试人员使用本身面向开发者设计强调代码即测试其设计理念天生就能和AI良好的结合。说句题外话本人作为测试人员这一年总是受到公司裁员的威胁深刻感受到未来可能没有明确的软件岗位划分AI的持续发展正在让多个岗位压扁成一个通用岗位。自然语言到测试脚本的无缝转换零学习成本生成专业脚本通过AI大模型用户只需用自然语言描述测试需求如测试/api/users接口50并发5分钟系统就能自动生成符合最佳实践的k6 JavaScript脚本。传统情况下测试人员很多不具备编写JavaScript脚本的能力但在AI时代这个被破除反而JMeter的脚本因为使用XML格式层级复杂、语法严格AI生成的准确率明显不如K6脚本。迭代优化机制智能体协调Script Writer生成脚本Script Critic进行评审如果评分低于8分则反馈优化最多3轮迭代确保代码质量。相反JMeter的XML错误难以定位需要熟悉JMeter内部结构离开JMeter工具就很难读写和评审测试代码JMeter是为适用测试人员不会写代码而设计的但在AI时代这反而成了一个弱势。当然JMeter也可以集成一些AI组件引入BeanShell‌或Groovy脚本来实现测试当整体的脚本调度还是基于XML。智能分析与优化建议深度结果解析AI不仅执行测试还能自动分析性能瓶颈。由于k6报告一般是json格式更容易被机器解析AI可直接理解字段含义无需额外训练列映射关系AI通过识别P95/P99响应时间超标的原因数据库查询慢、冷启动等并提供具体优化建议添加Redis缓存、优化数据库索引、启用CDN加速等。JMeter报告是JTL(CSV或XML)格式CSV虽然简单但信息有限XML冗长和可读性差不过JMeter也可以集成第三方插件把测试结果发给influxdb形成结构化数据也是能方便AI解析增加AI分析链路而这个功能在k6是原生自带的。预测模型与自适应调节k6正朝AI驱动方向发展智能体直接调用k6进行远程分布式压测并回收测试数据并分析结果得出结论包括基于历史数据预测系统瓶颈、根据实时指标动态调整虚拟用户数量实现精准压测。 k6和传统开源工具优势对比特性k6JMeterLocust单机性能​⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐学习曲线​⭐⭐⭐⭐⭐⭐⭐⭐⭐容器支持​⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐云原生集成​⭐⭐⭐⭐⭐⭐⭐⭐实时监控​⭐⭐⭐⭐⭐⭐⭐⭐⭐分布式测试​⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐AI集成丝滑性⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐社区生态​⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

更多文章