本文目录导读:

开展开源压测,通常遵循一个标准化的流程,从环境准备、工具选型、脚本编写、执行监控到结果分析,下面是一个通用的步骤指南,结合了主流开源工具(如 JMeter、Locust、k6、wrk、Vegeta 等)的实践。
第一阶段:规划与准备
在动手敲命令之前,先想清楚这几个问题:
- 明确压测目标:
- 性能基线:系统当前的“正常”性能数据。
- 容量规划:系统最多能支持多少并发用户/QPS(每秒查询数)。
- 稳定性/可靠性:长时间(如1小时、8小时)运行是否出问题(内存泄漏、OOM——内存溢出)。
- 瓶颈定位:找到数据库、CPU(中央处理器)、网络或某段代码的短板。
- 定义关键指标:
- TPS/QPS:每秒事务数/查询数。
- 响应时间:平均值、P50、P90、P95、P99(99%的请求都在该时间内完成)。
- 错误率:4xx/5xx的请求占比。
- 资源使用率:CPU、内存、磁盘IO、网络带宽。
- 搭建独立的压测环境:
- 千万不要压生产环境!(除非是类似双十一的演练且做好了熔断)。
- 环境配置(硬件、软件版本)尽量与生产一致。
第二阶段:工具选型
| 工具 | 特点 | 适合场景 | 学习成本 |
|---|---|---|---|
| Apache JMeter | GUI(图形用户界面)强大,支持插件多,支持复杂业务逻辑 | Web应用、API、数据库、FTP(文件传输协议)等几乎所有协议 | 中等(GUI拖拽) |
| Locust | Python脚本,代码定义行为,原生支持分布式 | 需要高度定制化、复杂的用户行为模拟 | 低(Python基础) |
| k6 | Go语言开发,脚本是JavaScript,单机性能极高,配置简单 | 微服务、API、高并发场景、CICD集成 | 低 |
| wrk | 基于C语言,性能极高,使用Lua脚本 | HTTP协议下的简单、高并发基准测试 | 低(命令行) |
| Vegeta | Go语言,命令行工具,专注于HTTP攻击 | 快速、简单的压测,性能报告中 | 极低 |
建议:
- 如果是新手或团队需要图形界面:选 JMeter。
- 如果是Python团队或需要复杂逻辑:选 Locust。
- 如果追求极致性能或集成到CI/CD(持续集成/持续部署):选 k6 或 wrk。
第三阶段:脚本开发与调试
以常用的 JMeter(通用)和 k6(现代、高效)为例:
场景 A:使用 JMeter(适合复杂场景)
- 创建测试计划:启动 JMeter GUI。
- 添加线程组:配置用户数(如100)、Ramp-Up(启动时间)、循环次数。
- 添加取样器(Sampler):
- HTTP 请求,配置协议、服务器IP、端口、路径、参数。
- 要点:如果需要参数化(如每个用户不同的Token),使用 CSV Data Set Config 或 用户参数。
- 添加监听器(Listener):
聚合报告、查看结果树(调试用,正式压测时建议关闭,否则消耗大量内存)。
- 添加断言(Assertion):检查响应结果是否符合预期(如状态码200,包含某个关键字)。
- 调试:先用1个用户跑一次,查看结果树确保脚本正确。
场景 B:使用 k6(适合开发/CI/CD)
-
安装:
brew install k6或 下载二进制包。 -
编写测试脚本(JS 文件,如
test.js):import http from 'k6/http'; import { check, sleep } from 'k6'; // 配置阶段 export let options = { vus: 10, // 10个虚拟用户 duration: '30s', // 持续30秒 thresholds: { http_req_duration: ['p(95)<500'], // 95%的请求应在500ms内 }, }; // 实际执行的主函数 export default function () { let res = http.get('https://test-api.example.com/users'); check(res, { 'status is 200': (r) => r.status === 200, 'response time < 300ms': (r) => r.timings.duration < 300, }); sleep(1); // 模拟用户思考时间 } -
调试:
k6 run test.js
第四阶段:执行压测
-
预热(Warm-Up):正式压测前,用小并发跑几十秒,让系统完成缓存加载、JIT(即时编译)编译等。
-
逐步加压:不要一下子把并发加到1000,而是从10开始,逐步增加到50、100、500,观察系统瓶颈。
- 在JMeter中:使用“Ramp-Up Period”(如100个用户用60秒启动)。
- 在k6中:使用
stages配置。
// k6 阶梯加压示例 export let options = { stages: [ { duration: '2m', target: 100 }, // 2分钟内逐步加到100 VUs(虚拟用户) { duration: '5m', target: 100 }, // 保持100 VUs 5分钟 { duration: '2m', target: 0 }, // 2分钟内降回0 ], }; -
监控资源:
- 压测机器:看CPU、内存是否打满(打满说明压测机器成为了瓶颈,需要分布式压测)。
- 被压测机器:
- 服务器:
top、htop、vmstat、iostat。 - 数据库:慢查询日志、连接数。
- 中间件:Web服务器的连接数、队列长度。
- 服务器:
第五阶段:结果分析与优化
压测结束后,拿到报告(JMeter的聚合报告、k6的终端输出/JSON报告),重点看:
- 是否达到目标:如果P99响应时间 > 2秒,或错误率 > 1%,说明系统不满足要求。
- 瓶颈在哪里:
- CPU 100%:代码存在死循环或计算密集型任务,需要优化算法或扩容。
- 磁盘IO高:频繁写日志或数据库IO问题,考虑SSD(固态硬盘)、缓存、优化SQL。
- 响应时间逐渐升高:可能是线程池耗尽或内存GC(垃圾回收)问题。
- 连接数爆满:数据库连接池或HTTP连接池配置太小。
- 反复验证:修复问题后,在相同条件(并发数、环境)下重新执行压测,对比结果。
第六阶段:进阶与自动化
- 分布式压测:单台机器可能模拟不出几十万的并发(如 JMeter 耗尽线程),可以搭建主从模式(Master-Slave)或多台服务器负载均衡。
- JMeter: 使用远程启动。
- k6: 使用
k6 cloud(云服务)或k6 run --out influxdb=...结合Grafana(开源可视化平台)做监控。
- 集成CI/CD:
- 在 Jenkins/GitLab CI 中,写好压测脚本。
- 设置阈值(Thresholds),
p95 > 500ms则构建失败。 - 注意:在CI环境中压测要控制好参数,不要压垮共享的测试环境。
- 数据持久化与可视化:
- 工具:JMeter + InfluxDB + Grafana。
- 工具:k6 + InfluxDB + Grafana(非常流行)。
- 优点:能看到实时数据趋势,并比较不同版本的压测曲线。
关键避坑指南
- 不要自己压自己:压测脚本所在机器的资源要足够,否则测出来的数据是假的。
- 参数化是灵魂:不要让所有用户都使用同一个账号、搜索同一个关键词,要用CSV文件或函数生成随机数据。
- 忘记监听器:JMeter 的“查看结果树”和“图形结果”非常耗资源,正式压测时请关闭,只保留“聚合报告”或使用后端监听器写数据库。
- 关注P99而非平均值:平均响应时间可能会掩盖少数极慢请求的问题。
- 先小后大:永远从小并发开始,观察系统表现,再逐步加压。
- 结果要可复现:记录压测时的环境配置、并发数、持续时间、脚本版本,方便后续对比。