性能压测不是上线前的走过场,而是用性能压测工具在真实流量放大之前,把系统的瓶颈、超时与内存泄漏提前暴露出来。无论是为了大促容量规划、发布前的回归压测,还是在容量红线逼近时做扩容决策,压测都是后端团队的刚需。k6、JMeter、Locust 是当前开发者圈最常被拿来对比的三款方案,但它们定位差异极大,选错会让压测本身变成负担:有人用 JMeter 去压一个简单接口,光搭 GUI 就花半天;也有人用 Locust 去压 JDBC,结果要自己造一堆轮子。
一、三款工具定位速览
一句话区分:k6 为开发者而生、脚本即代码;JMeter 是企业级 GUI 全能选手、协议覆盖最广;Locust 用纯 Python 写分布式压测,适合需要复杂逻辑编排的团队。需要强调的是,三者并非互斥——很多团队会同时保留 k6 做日常 CI 门禁、JMeter 做存量复杂协议回归,按场景各取所长。
| 维度 | k6 | JMeter | Locust |
|---|---|---|---|
| 脚本语言 | JavaScript (ES6) | GUI/Java DSL | Python |
| 架构 | 单进程 Go 引擎 | 多线程 Java | 事件驱动协程 |
| 协议 | HTTP/gRPC/WS | 几乎全覆盖 | HTTP 为主 |
| 上手成本 | 低 | 中 | 低(会 Python 即可) |
| 最佳场景 | CI 门禁、接口压测 | 企业级复杂协议 | 自定义逻辑压测 |
二、k6:为开发者而生的代码化压测
k6 用 Go 编写引擎、用 JS 写脚本,天然适合塞进流水线。它最核心的两个概念是 check(单条断言,失败只记录不中断)和 threshold(阈值,不达标直接让脚本非零退出)。前者用来观察”哪些请求不健康”,后者用来当 CI 门禁——这是 k6 区别于另外两款的最大卖点:压测结果可以程序化判定,而不是人盯着报表。
import http from 'k6/http';
import { check, sleep } from 'k6';
import { Rate } from 'k6/metrics';
export const options = {
vus: 50,
duration: '30s',
thresholds: {
http_req_duration: ['p(95)<500'], // P95 必须 < 500ms
http_req_failed: ['rate<0.01'], // 错误率 < 1%
},
};
export default function () {
const res = http.get('https://api.example.com/orders');
check(res, { 'status 200': (r) => r.status === 200 });
sleep(1);
}
把压测接进 GitHub Actions 搭建的 CI/CD 流水线 后,阈值不达标就会让构建失败,相当于给每次发布加了一道性能红线。
2.1 在 CI 中跑 k6 阈值门禁
# .github/workflows/loadtest.yml
name: loadtest
on: [push]
jobs:
k6:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run k6 cloud/local
uses: grafana/k6-action@v0.3
with:
filename: scripts/orders.js
# 阈值未通过 → 步骤非零退出 → 流水线失败
三、JMeter:企业级 GUI 压测瑞士军刀
JMeter 的强项是协议覆盖面:HTTP、FTP、JDBC、JMS、SMTP 都能压,老系统里那些非 HTTP 的私有协议往往只有它能顶上。日常更推荐用 GUI 录制脚本、再用命令行无界面跑,避免 GUI 模式本身的 Swing 界面吃掉资源拖累数据。工程化时记得加三类元件:断言(Response Assertion 校验返回体)、CSV Data Set Config 做参数化(避免所有线程打同一个账号)、定时器(Constant Throughput Timer 控吞吐)。需要更大压力就开分布式,由一台 Controller 调度多台 Agent。
# 非 GUI 模式跑测试并生成 HTML 报告
jmeter -n -t orders_test.jmx -l result.jtl -e -o report-html/
# 关键 JVM 调优(bin/jmeter 或 setenv)
export HEAP="-Xms4g -Xmx4g -XX:MaxMetaspaceSize=512m"
四、Locust:用 Python 写分布式压测
Locust 把”用户行为”建模成 Python 类,适合需要按业务流编排请求的场景。协程(gevent)模型让它用少量进程就能起上万并发,而且你能用真正的 Python 控制流写分支、循环、依赖前一步返回的数据——这是 JMeter 的 GUI 树很难优雅表达的地方。除了命令行,它自带一个 Web UI 实时看 RPS 和失败率,也能用 --headless 跑进 CI。复杂场景还能写自定义 load_shape 实现双十一式的脉冲流量。
from locust import HttpUser, task, between
class OrderUser(HttpUser):
wait_time = between(1, 3)
@task(3)
def list_orders(self):
self.client.get("/orders", name="GET /orders")
@task(1)
def create_order(self):
self.client.post("/orders", json={"sku": "A1", "qty": 1})
# 分布式:master + 多个 worker
# locust -f order_locust.py --master
# locust -f order_locust.py --worker --master-host=10.0.0.1
五、怎么选:决策表
选型没有标准答案,关键看你的团队技能栈和压测目标。下面这张表把最常见的四种处境映射到首选工具,照着对号入座基本不会错;若团队同时具备 JS 和 Python 能力,k6 和 Locust 可以并行,JMeter 则留作存量复杂协议的兜底。
| 你的处境 | 首选 | 理由 |
|---|---|---|
| 想把压测塞进 CI | k6 | 脚本即代码、阈值门禁开箱即用 |
| 要压非 HTTP 老协议 | JMeter | 协议覆盖最广 |
| 压测逻辑很复杂 | Locust | Python 表达力强、易复用 |
| 团队不会写代码 | JMeter | 纯 GUI 也能搭起来 |
六、压测指标到底看什么
新手容易只盯 RPS(每秒请求数),但 RPS 高不代表系统健康。真正该同时盯的是四组指标:虚拟用户数(VU,并发压力来源)、响应时间分位值(RT 的 P50/P95/P99,P99 才暴露长尾慢请求)、错误率(5xx/超时占比)、吞吐量(系统实际处理能力)。看分位而非平均值,是因为平均值会把 1% 的 3 秒慢请求稀释掉,而线上投诉往往就来自那 1%。
| 指标 | 含义 | 健康参考 |
|---|---|---|
| VU | 并发虚拟用户 | 随场景设定 |
| P95 RT | 95% 请求耗时 | 接口 SLA 内 |
| P99 RT | 长尾耗时 | 不超过 P95 的 2 倍 |
| 错误率 | 失败请求占比 | < 0.1% |
| 吞吐量 | 系统真实处理力 | 出现拐点即瓶颈 |
七、阶梯加压:别一上来就打满
很多压测翻车是因为”一开就是最大并发”,结果曲线直接塌方,分不清是应用还是压测机的问题。正确做法是阶梯加压(ramp-up):逐步抬升 VU,观察吞吐随压力变化的拐点。下面是 k6 的阶梯配置,从 0 慢慢加到 200 再回落,能清晰画出系统的容量曲线。
export const options = {
stages: [
{ duration: '1m', target: 50 }, // 预热
{ duration: '3m', target: 200 }, // 阶梯加压
{ duration: '1m', target: 200 }, // plateau 观察
{ duration: '1m', target: 0 }, // 降压回收
],
thresholds: { http_req_duration: ['p(95)<500'] },
};
八、把压测接进可观测体系
压测孤军作战价值有限。把 k6 的 Prometheus 远端写打开,指标直接进 Prometheus + Grafana 监控面板,压测曲线和系统 CPU、QPS 同屏对照,瓶颈一目了然。若压出 502/504,可对照 Nginx 502/504 排查实录 从超时与连接池入手;压出数据库抖动则回看 MySQL 深度调优 的执行计划与参数。前端侧同样可参考 前端性能优化 Lighthouse 实战 做端到端收敛。
九、新手常踩的 4 个坑
| 坑 | 现象 | 解法 |
|---|---|---|
| 压测机先被打满 | 自身 CPU 100%,曲线失真 | 分布式起多台、监控压测机 |
| 只压单接口 | 漏掉真实业务流 | 按用户旅程编排请求 |
| 没有思考时间 | 比生产更暴烈 | 加 sleep/wait_time |
| 不看服务端指标 | 只盯 RPS | 联动监控面板看资源 |
十、小结
三款工具没有绝对优劣:要 CI 门禁选 k6,要复杂协议选 JMeter,要灵活逻辑选 Locust。真正重要的是把压测常态化、接进监控,让每一次发布都有性能兜底。建议从今天起就挑一款最顺手的,把团队核心接口写上压测脚本并挂进流水线——等下次大促或扩容评审时,你会感谢现在埋下的这条性能红线。




