当前位置: 首页 > web >正文

Grafana k6 性能测试

Grafana k6 是一款现代化的开源性能测试工具,专为测试API、微服务和网站而设计。

它采用JavaScript/TypeScript作为脚本语言,提供了简洁的API和强大的负载模拟能力,同时易于集成到CI/CD流程中。

本文将带您从基础到进阶,全面掌握k6的使用方法。

一、安装与环境准备

1.1 支持的操作系统

k6支持Windows、macOS和Linux,同时提供Docker镜像,方便在任何环境中运行。

1.2 安装步骤

macOS (Homebrew):

brew install k6

Windows (Chocolatey):

choco install k6

Linux (Ubuntu/Debian):

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C3959F7F5288
echo "deb https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
sudo apt update && sudo apt install k6

Docker:

docker pull grafana/k6

1.3 验证安装

安装完成后,运行以下命令验证:

k6 version

如果安装成功,会显示类似以下内容:

k6 v0.49.0 ((devel), go1.21.0, linux/amd64)

二、k6核心概念

在编写测试脚本前,理解k6的核心概念至关重要:

  1. 虚拟用户(VUs): 模拟真实用户的并发单元,每个VU独立执行脚本逻辑

  2. 场景(Scenarios): 定义测试的负载模式,如并发数、持续时间、递增方式等

  3. 生命周期:

    • init阶段: 脚本最外层代码,只执行一次,用于导入模块和定义全局变量
    • setup函数: 测试开始前执行一次,用于准备测试数据
    • VU函数: 每个虚拟用户重复执行的核心测试逻辑
    • teardown函数: 测试结束后执行一次,用于清理测试环境
  4. 指标(Metrics): 衡量系统性能的数据,如响应时间、错误率等

  5. 检查(Checks): 验证系统响应是否符合预期的断言机制

  6. 阈值(Thresholds): 定义性能指标的可接受范围,用于自动判断测试是否通过

三、第一个k6测试脚本

让我们从一个简单的HTTP GET请求测试开始,创建文件basic-test.js

import http from 'k6/http';
import { check, sleep } from 'k6';// 测试配置选项
export const options = {vus: 10,          // 并发虚拟用户数duration: '30s',  // 测试持续时间
};// 虚拟用户执行的主要函数
export default function() {// 发送GET请求const res = http.get('https://httpbin.test.k6.io/get');// 检查响应是否符合预期check(res, {'状态码为200': (r) => r.status === 200,'响应时间小于500ms': (r) => r.timings.duration < 500,});// 每个迭代后暂停1秒,模拟用户思考时间sleep(1);
}

3.1 脚本解析

  1. 导入模块: 我们导入了http模块用于发送HTTP请求,check用于验证响应,sleep用于模拟用户等待时间。

  2. 配置选项:

    • vus: 同时运行的虚拟用户数量
    • duration: 测试总持续时间
  3. VU函数:

    • http.get(): 发送HTTP GET请求到指定URL
    • check(): 验证响应状态码和响应时间
    • sleep(1): 暂停1秒,避免请求过于密集

3.2 运行测试

执行以下命令运行测试:

k6 run basic-test.js

如果使用Docker,执行:

cat script.js | docker run --rm -i grafana/k6 run -

四、测试结果分析

测试运行时和结束后,k6会输出详细的测试结果。让我们理解一些关键指标:

  █ TOTAL RESULTSchecks_total.......: 440     14.035254/schecks_succeeded...: 100.00% 440 out of 440checks_failed......: 0.00%   0 out of 440✓ ???????00✓ ?????????500msHTTPhttp_req_duration..............: avg=188.19ms min=60.93ms med=193.8ms max=338.83ms p(90)=309.64ms p(95)=310.83ms{ expected_response:true }...: avg=188.19ms min=60.93ms med=193.8ms max=338.83ms p(90)=309.64ms p(95)=310.83mshttp_req_failed................: 0.00%  0 out of 440http_reqs......................: 440    14.035254/sEXECUTIONiteration_duration.............: avg=1.41s    min=1.36s   med=1.37s   max=2.26s    p(90)=1.38s    p(95)=1.4siterations.....................: 220    7.017627/svus............................: 10     min=10       max=10vus_max........................: 10     min=10       max=10NETWORKdata_received..................: 772 kB 25 kB/sdata_sent......................: 30 kB  958 B/s

关键指标解释:

  • http_req_duration: HTTP请求的总持续时间,包含了建立连接、发送请求、等待响应和接收响应的时间
    • p(90)p(95)是百分位数,表示90%或95%的请求在此时间内完成
  • http_req_failed: 失败请求的比例,理想情况下应为0
  • http_reqs: 每秒处理的请求数(RPS),反映系统吞吐量
  • vus: 当前并发虚拟用户数
  • iterations: 完成的测试迭代次数

五、进阶测试场景

5.1 复杂场景配置

k6的场景(Scenarios)功能允许您定义更复杂的负载模式。创建scenarios-test.js

import http from 'k6/http';
import { check, sleep } from 'k6';export const options = {scenarios: {// 场景1: 逐步增加负载ramp_up: {executor: 'ramping-vus',startVUs: 0,stages: [{ duration: '30s', target: 50 },  // 30秒内从0增加到50个VU{ duration: '1m', target: 50 },   // 维持50个VU 1分钟{ duration: '20s', target: 0 },   // 20秒内减少到0个VU],gracefulRampDown: '10s',  // 优雅地减少负载},// 场景2: 恒定负载constant_load: {executor: 'constant-vus',vus: 20,duration: '2m',startTime: '1m50s',  // 在第一个场景开始后1分50秒启动},},
};export default function() {const res = http.get('https://httpbin.test.k6.io/get');check(res, {'状态码为200': (r) => r.status === 200,});sleep(1);
}

k6提供多种执行器(executor)类型,适用于不同测试场景:

  • ramping-vus: 逐步增加或减少虚拟用户数
  • constant-vus: 维持恒定的虚拟用户数
  • constant-arrival-rate: 维持恒定的请求率
  • ramping-arrival-rate: 逐步增加或减少请求率
  • per-vu-iterations: 每个虚拟用户执行固定次数的迭代

5.2 设置阈值(Thresholds)

阈值用于定义性能指标的可接受范围,创建thresholds-test.js

import http from 'k6/http';
import { check, sleep } from 'k6';export const options = {vus: 10,duration: '30s',thresholds: {// 错误率必须小于1%http_req_failed: ['rate<0.01'],// 95%的请求响应时间必须小于500mshttp_req_duration: ['p(95)<500'],// 每秒请求数至少为10http_reqs: ['rate>10'],},
};export default function() {const res = http.get('https://httpbin.test.k6.io/get');check(res, {'状态码为200': (r) => r.status === 200,});sleep(1);
}

如果任何阈值未达标,k6将以非零状态码退出,这在CI/CD集成中非常有用。

5.3 处理认证与状态保持

大多数API测试需要处理认证,创建auth-test.js

import http from 'k6/http';
import { check, sleep } from 'k6';export const options = {vus: 5,duration: '30s',
};// 测试开始前执行一次,用于登录获取token
export function setup() {const loginRes = http.post('https://test-api.k6.io/auth/token/login/', {username: 'test-user',password: 'test-passwd',});const token = loginRes.json('access');check(loginRes, {'登录成功': (r) => r.status === 200 && token !== '',});return { token: token };
}// 每个虚拟用户执行的测试逻辑
export default function(data) {const params = {headers: {Authorization: `Bearer ${data.token}`,'Content-Type': 'application/json',},};// 访问受保护的API端点const res = http.get('https://test-api.k6.io/my/crocodiles/', params);check(res, {'状态码为200': (r) => r.status === 200,'响应包含鳄鱼数据': (r) => JSON.parse(r.body).length > 0,});sleep(1);
}// 测试结束后执行一次,用于清理
export function teardown(data) {const params = {headers: {Authorization: `Bearer ${data.token}`,},};// 登出(如果API支持)const res = http.post('https://test-api.k6.io/auth/token/logout/', null, params);check(res, {'登出成功': (r) => r.status === 204,});
}

这个脚本展示了如何:

  1. setup函数中执行登录并获取认证token
  2. 将token传递给VU函数
  3. 在每个请求中使用token进行认证
  4. teardown函数中执行登出清理

5.4 测试数据管理

对于更真实的测试,我们需要使用不同的测试数据。创建data-driven-test.js

import http from 'k6/http';
import { check, sleep, SharedArray } from 'k6';
import { Counter } from 'k6/metrics';// 自定义指标,用于跟踪不同类型的请求
const successfulSearches = new Counter('successful_searches');
const failedSearches = new Counter('failed_searches');// 从JSON文件加载测试数据(只在init阶段执行一次)
const data = new SharedArray('搜索关键词', function() {return JSON.parse(open('./search-terms.json')).terms;
});export const options = {vus: 10,duration: '30s',thresholds: {http_req_duration: ['p(95)<500'],successful_searches: ['rate>0.95'],},
};export default function() {// 为每个VU选择不同的关键词(基于VU ID和迭代次数)const term = data[(__VU * __ITER) % data.length];// 发送搜索请求const res = http.get(`https://httpbin.test.k6.io/get?search=${encodeURIComponent(term)}`);// 检查响应const isSuccessful = check(res, {'状态码为200': (r) => r.status === 200,'响应包含搜索词': (r) => r.body.includes(term),});// 更新自定义指标if (isSuccessful) {successfulSearches.add(1);} else {failedSearches.add(1);}sleep(1);
}

创建配套的search-terms.json文件:

{"terms": ["k6", "performance", "testing", "api", "grafana", "load", "stress", "vus", "thresholds", "scenarios"]
}

这个脚本展示了:

  1. 使用SharedArray高效加载和共享测试数据
  2. 为不同的虚拟用户分配不同的测试数据
  3. 创建和使用自定义指标

六、结果导出与可视化

6.1 导出结果到文件

k6可以将测试结果导出为多种格式:

# 导出为JSON
k6 run --out json=results.json basic-test.js# 导出为CSV
k6 run --out csv=results.csv basic-test.js# 同时导出多种格式
k6 run --out json=results.json --out csv=results.csv basic-test.js

6.2 与Grafana集成

将k6与Grafana集成可以获得更强大的可视化和分析能力:

  1. 启动InfluxDB(作为数据存储):
docker run -d -p 8086:8086 \-e INFLUXDB_DB=k6 \--name influxdb \influxdb:1.8
  1. 启动Grafana:
docker run -d -p 3000:3000 \--link influxdb:influxdb \--name grafana \grafana/grafana
  1. 在Grafana中配置数据源:

    • 访问http://localhost:3000(默认用户名/密码:admin/admin)
    • 添加InfluxDB数据源,URL设置为http://influxdb:8086,数据库名为k6
  2. 导入k6官方仪表板:

    • 在Grafana中导入仪表板ID:1443
    • 选择配置好的InfluxDB数据源
  3. 运行测试并发送结果到InfluxDB:

k6 run --out influxdb=http://localhost:8086/k6 basic-test.js

现在,您可以在Grafana中实时查看测试指标和图表。

七、CI/CD集成

k6可以轻松集成到CI/CD流程中,作为质量门禁的一部分。以下是GitHub Actions的配置示例(创建.github/workflows/k6-test.yml):

name: k6 Performance Teston:push:branches: [ main ]pull_request:branches: [ main ]jobs:k6-test:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v3- name: Setup k6uses: k6io/action@v0.1with:k6-version: latest- name: Run k6 testrun: k6 run tests/load-test.js- name: Upload test resultsif: always()uses: actions/upload-artifact@v3with:name: k6-resultspath: results.json

这个配置将在每次推送到main分支或创建PR时自动运行k6测试,如果测试失败(阈值未达标),CI流程也会失败。

八、最佳实践

  1. 从简单开始: 先创建基础测试,验证基本功能,再逐步增加复杂度

  2. 使用真实数据: 测试数据应尽可能接近生产环境的真实数据

  3. 定义明确的阈值: 根据业务需求和SLA定义清晰的性能阈值

  4. 逐步增加负载: 从低负载开始,逐步增加,观察系统在不同负载下的表现

  5. 隔离测试环境: 确保测试环境与生产环境隔离,避免影响真实用户

  6. 监控系统资源: 在测试期间监控服务器CPU、内存、磁盘I/O等资源使用情况

  7. 版本控制测试脚本: 将测试脚本纳入版本控制,与应用代码一起演进

  8. 自动化测试: 将性能测试集成到CI/CD流程中,尽早发现性能问题

  9. 分析瓶颈: 不仅关注响应时间,还要分析系统瓶颈所在(数据库、网络、应用服务器等)

  10. 定期执行: 定期运行性能测试,跟踪性能变化趋势

九、总结

通过本教程,您已经掌握了Grafana k6的核心功能和使用方法,包括:

  • 安装和配置k6环境
  • 理解k6的核心概念和生命周期
  • 编写基础和进阶的测试脚本
  • 配置复杂的测试场景和阈值
  • 处理认证和管理测试数据
  • 导出和可视化测试结果
  • 集成k6到CI/CD流程

k6提供了丰富的功能和灵活的API,能够满足从简单到复杂的各种性能测试需求。随着您对k6的深入使用,可以探索更多高级功能,如自定义指标、WebSocket测试、分布式测试等。

要了解更多信息,请参考k6官方文档:https://k6.io/docs/

http://www.xdnf.cn/news/18781.html

相关文章:

  • 深度模块化剖析:构建一个健壮的、支持动态Cookie和代理的Python网络爬虫
  • 保姆级Maven安装与配置教程(Windows版)
  • 基于 MATLAB 的信号处理实战:滤波、傅里叶变换与频谱分析
  • 从文本树到结构化路径:解析有限元项目架构的自动化之道
  • 服务器硬件电路设计之 SPI 问答(四):3 线 SPI、Dual SPI 与 Qual SPI 的奥秘
  • Leetcode 3660. Jump Game IX
  • k8sday16调度器
  • MSF基础知识
  • Java 内存模型(JMM)与并发可见性:深入理解多线程编程的基石
  • Java:HashMap的使用
  • K8s 实战:六大核心控制器
  • 什么是 Nonce?
  • 电力电子simulink练习10:反激Flyback电路搭建
  • Linux 的 TCP 网络编程常用API
  • 图像均衡化详解:从直方图均衡到 CLAHE,让图片告别 “灰蒙蒙“
  • 高数 不定积分(4-3):分部积分法
  • 使用虚幻引擎5(UE5)开发类似《原神》的开放世界游戏:从技术架构到实践指南
  • 内网后渗透攻击--域控制器安全(1)
  • 单表查询-分析函数的应用
  • 重置MySQL数据库的密码指南(Windows/Linux全适配)
  • 在 Ruby 客户端里用 ES|QL
  • WSL-linux部署IndexTTS 记录(含本地 CUDA/cuDNN 编译依赖说明)
  • 鸿蒙 ArkTS 开发:Number、Boolean、String 三种核心基本数据类型详解(附实战案例)
  • 夜间跌倒检测响应速度↑150%!陌讯多模态骨架追踪算法在智慧养老院的落地实践
  • 手写MyBatis第32弹-设计模式实战:Builder模式在MyBatis框架中的精妙应用
  • Anaconda搭建keras开发环境小记
  • EP01:【DA】数据分析的概述
  • 【LeetCode】分享|如何科学的刷题?
  • 2025年渗透测试面试题总结-31(题目+回答)
  • 基于springboot的高校后勤保修服务系统/基于android的高校后勤保修服务系统app