做Web接口的并发压力测试不是证实业务对不对,是在高并发下系统能撑多少流量、响应快不快、稳不稳定。
一、并发压力测试要做什么
吞吐量(TPS/QPS)每秒能处理多少请求,体现系统容量。
响应时间,平均值、中位数、95/99分位线,长尾延迟。
错误率,超时、500、连接拒绝等,必须在可接受范围内。
资源利用率,CPU、内存、磁盘IO、网络带宽、数据库连接池等是不是已到短板。
并发用户数,系统在可接受响应时间内支持的最大并发数。
测试过程:小流量预压 -阶梯加压 -找到拐点 - 极限施压 - 不断负载测试。
二、主流工具选择
JMeter:图形化界面,用线程组模拟并发,丰富的插件体系。上手快,支持参数化、断言、分布式压测,报表需要额外配置或配合 Grafana。适合大多数传统项目的 HTTP 接口压测。
Gatling:根据 Scala 的 DSL 编写压测脚本,报表非常漂亮且自动生成,资源消耗更低,单个节点能产生比 JMeter 更高的并发。适合有编码能力、追求简洁美观报表的团队。
Locust:纯 Python 编写,用代码定义用户行为,分布式部署简单(master-worker 方式),通过 Web UI 实时观察压测。适合 Python 技术栈,或者希望灵活定制压测思路的场景。
wrk / wrk2:轻量级命令行工具,Lua 脚本扩展,能打出很高的并发,占用资源极低,适合简单的单接口标准压测,不适合复杂链路。
k6:用 JavaScript 编写脚本,天生为了 CI/CD 集成而设计,可以输出 JSON 数据,并直接对接 Grafana 云端或 Prometheus。适合希望将压测纳入 DevOps 流水线的团队。
如果刚起步,建议从JMeter或Locust开始,一个能快速图形化上手,一个能用Python灵活控制。
三、具体怎么做
1. 确定压测目的和范围
要压哪个接口(单接口标准?还是混合业务场景,比如“登录→浏览商品→下单”)?
期望的峰值 QPS 是多少?未来一段时间业务增长预期?
可接受的响应时间上限是多少(如 P99 小于 500ms)?
错误率要控制在多少以下(一般要求 0%,重点业务不允许失败)?
根据这些确定测试场景和通过标准。
2. 隔离环境准备
压测必须在独立的、尽量贴近生产配置的测试环境上进行,绝对不能在线上直接搞,也不要在共享的测试环境里影响其他团队。
应用、数据库、缓存、消息队列等都要独立。
前置数据量要模拟真实规模(如账号数、商品数、历史订单量),否则数据库索引优化效果可能完全不同。
部署监控体系:应用端(JVM、GC、线程)、服务端(CPU、内存、网络)、数据库端(慢查询、连接数)。常用组合是 Prometheus + Grafana + node_exporter / jmx_exporter 等。
3. 编写压测脚本场景
压测脚本是把业务操作转成代码或配置,并加入参数化、断言和思考时间。
以 Locust 为例,编写一个登录后查询用户信息的场景:
python
from locust import HttpUser, task, between
class QuickstartUser(HttpUser):
wait_time = between(1, 2) # 模拟用户操作间隔
def on_start(self):
# 登录并获取 token
resp = self.client.post("/api/login",
json={"username": "testuser", "password": "123456"})
self.token = resp.json()["token"]
@task(3) # 权重,该任务执行频率更高
def view_profile(self):
self.client.get("/api/user/profile",
headers={"Authorization": f"Bearer {self.token}"})
@task(1)
def update_nickname(self):
self.client.put("/api/user/profile",
json={"nickname": "load_test"},
headers={"Authorization": f"Bearer {self.token}"})
用 on_start 做前置登录,避免每次请求都登录。
通过 @task 的权重模拟不同接口的流量比例。
参数化数据(如不同用户ID、不同商品)要用循环或读取文件,别用死数据,否则缓存命中率不真实。
使用JMeter的思路:
在线程组里设置并发数、加压方法、循环次数。
用 HTTP 请求创建接口调用,添加 CSV 数据文件设置做参数化。
用JSON断言检查返回码和字段,标记失败请求。
使用聚合报告或后端监听器将数据发往 InfluxDB/Grafana 展示。
4. 执行压测并逐步加压
不要一上来就设置几千并发,要像做实验一样慢慢来
阶段一:标准测试。只用 1~5 个并发,确定脚本无错误,单接口性能是不是正常。
阶段二:摸高测试。按阶梯式增加并发,如每 2 分钟增加 50 并发,同时观察 TPS、响应时间、错误率的变化。当 TPS 不再增长甚至下降,或者响应时间突然飙升、错误率骤增,说明快到性能拐点了。
阶段三:极限测试。在拐点附近保持高并发一段时间,看系统会不会 OOM、数据库连接池耗尽或雪崩。
阶段四:稳定性测试。用略低于最大容量的并发数(如 70%~80% 峰值负载),不断压测数小时甚至更久,检查内存泄漏、日志堆积、数据库慢查询等问题。
执行时最好用命令行非 GUI 方式,减少压测工具自身的资源消耗。如:
JMeter:jmeter -n -t test.jmx -l result.jtl
Locust:locust -f script.py --headless -u 1000 -r 50 --run-time 10m --csv=result
k6:k6 run script.js
5. 实时监控并定位问题
压测工具侧:实时 TPS、响应时间分位数、失败率。
服务端资源:CPU 利用率(用户态/内核态/等待IO)、内存(是不是频繁 GC)、磁盘 IO、网络带宽包。
应用级标准:请求队列长度、线程池占用、数据库连接池活跃数、慢查询日志。
中间件:Redis 命中率、消息队列积压情况。
一旦发现异常(如大量超时),要保留现场,抓取thread dump、jmap堆栈、数据库processlist,方便后续分析短板。
6. 分析报告输出结果
系统在某个并发下,QPS 达到多少,平均/95线响应时间是多少,错误率是多少。
性能短板在哪里:是代码慢、数据库SQL缺索引、Redis热点key、连接池太小、还是服务器硬件到顶了。
优化建议:如增加索引、调整连接池、引入缓存、异步化、扩容等。
报告可以包含趋势图(QPS 和响应时间的关系曲线),直观展示拐点位置,让研发和架构师一眼看懂问题。
Web 接口并发压力测试是:确立标准 - 选工具 - 隔离环境 - 编写场景脚本 - 阶梯加压 - 实时监控 - 定位短板 - 输出报告。