压力测试的四种核心类型
做接口压力测试,你首先得搞清楚一件事:你究竟想测什么?
很多人上来就拿着工具一顿猛压,压完一看报告——响应时间涨了,没报错,然后就交差了。这其实挺浪费的。我见过不少团队,压测报告写得花里胡哨,但核心问题一个都没暴露出来。
为什么会这样?说白了,就是没搞明白压力测试的分类。
我个人习惯把压测分成四类:负载测试、压力测试、稳定性测试和峰值测试。每一类都有它特定的目标,工具、场景、指标都不一样。你混着用,数据就变味儿了。
核心观点:测试类型的选择,决定了你能从压测中得到什么信息。选错了类型,再漂亮的数据也救不了你。
负载测试(Load Testing)
负载测试,说白了,就是给系统施加一个预期的正常压力。
什么叫预期的正常压力?就是你根据业务预估,系统在线上日常跑的时候,大概会承受多大的并发量、多高的 QPS。比如你们团队拍脑袋说「双十一预计 10 万 QPS」,那你就按 10 万去压。
目的是什么?验证系统能不能在这个压力下正常跑。响应时间别超标,错误率别超过 0.1%,CPU 别飙到 100%。
我之前做一个电商秒杀系统的负载测试时,就踩过一个坑。团队预估峰值是 5 万 QPS,我按 5 万压了一轮,结果系统挺稳的。大家都很高兴,准备上线了。
但我多留了个心眼——我按 6 万、7 万、8 万 继续往上加。你猜怎么着?到 7 万 2 的时候,数据库连接池直接爆了,服务大面积超时。
嗯,这其实已经不是负载测试了,已经在往压力测试的方向走了。但这个故事告诉我们一个道理:负载测试的环境,一定要尽量贴近真实线上环境。
我的习惯:做负载测试时,我会把并发数从 50% 的预估压力开始,逐步加到 100%。每挡跑 5 分钟,记录稳定后的指标。这样能看出系统在压力递增过程中的变化曲线。
负载测试的典型工具配置:
# 一个简单的负载测试场景配置(以 Locust 为例)
from locust import HttpUser, task, between
class WebsiteUser(HttpUser):
wait_time = between(1, 3) # 模拟用户在操作间的思考时间
@task
def search(self):
self.client.get("/api/secret/search?keyword=test")
@task(3)
def detail(self):
self.client.get("/api/secret/detail/12345")
# 注意:这里 wait_time 很关键,别设为 0
# 我见过有人设成 0,结果压出来的数据完全失真
压力测试(Stress Testing)
压力测试和负载测试最大的区别是什么?
负载测试是「够用就行」,压力测试是「看看底线在哪」。
压力测试的目标很简单:找到系统的崩溃点。你不断加大压力,直到系统撑不住为止。然后你就能知道:并发数到多少会崩?响应时间从哪个点开始雪崩?资源是哪个先耗尽的?
我刚开始做测试的时候,也犯过这种错误——压力测试做了一半,系统开始报错,我就停了。觉得「找到问题了,修好再测」。后来一位老前辈跟我说:「错了也别停,压下去,看看系统崩溃的时候是什么样。」
这句话我一直记到现在。
因为很多时候,系统在接近崩溃时的表现,才是你最需要关注的东西。比如:
- 是直接挂掉,还是优雅降级?
- 错误是突然暴涨,还是慢慢爬坡?
- 崩溃后能自己恢复吗?还是需要人工介入?
这些信息,只有压力测试能告诉你。
注意:压力测试有风险。乱压真的能把线上环境搞挂。我建议你:
- 永远不要在线上环境直接做压力测试
- 准备好回滚方案,或者自动熔断机制
- 观察关键指标(CPU、内存、连接数)在崩溃前的变化趋势
稳定性测试(Stability / Endurance Testing)
稳定性测试,也叫持久测试。目标不是看系统能不能扛住高压,而是看系统能不能长时间稳定运行。
你想想看,很多问题不是刚上线就暴露的。内存泄漏、连接池不释放、文件句柄没关闭、定时任务堆积……这些问题,你要跑几小时甚至几天才能发现。
我有一个亲身经历。之前做一个消息推送服务,负载测试、压力测试都过了,数据很漂亮。结果上线第三天,服务挂了。查了半天,发现是一个小小的缓存组件,每次写入都会创建新对象,但从来不回收。8 小时后,堆满了。
从那以后,我再也不敢轻视稳定性测试。所有核心服务的压测方案里,都加了一轮 72 小时稳定性测试。
稳定性测试的几个关键点:
- 压力水平:通常取预估峰值的 60%-80%,不要满负荷
- 持续时间:最少 4 小时,核心服务建议 24-72 小时
- 监控粒度:每分钟记录一次关键指标,关注变化趋势
我的判断标准:如果系统在 24 小时的稳定性测试中,响应时间的 P99 波动不超过 10%,内存使用量增长不超过 5%,我就认为它通过了稳定性测试。
峰值测试(Spike Testing)
峰值测试比较特殊。它模拟的是流量突然暴涨的场景。
典型的例子:微博热搜、抢购秒杀、突发热点新闻。流量可能在几秒内飙升几十倍,然后缓慢回落。这跟负载测试慢慢加压力的方式完全不同。
峰值测试要回答的问题是:
- 系统能承受瞬时多少倍的流量冲击?
- 流量回落后,系统能快速恢复吗?
- 有没有自动扩缩容机制?触发阈值是多少?
我之前遇到过最典型的情况:一个在线教育平台,晚上 8 点准时推课。用户习惯性地在那几分钟涌进来,QPS 从 500 瞬间跳到 8000。你猜怎么着?负载测试跑得好好的,一遇到这种峰值,网关直接挂了。
原因后来查出来,是网关的限流组件有个 bug:超过阈值后不是排队等待,而是直接熔断,而且熔断恢复时间设成了 30 秒。30 秒啊,对于这种场景,黄花菜都凉了。
峰值测试技巧:不要把压力全压在一瞬间。现实中流量暴涨也是有个过程的。我通常用 3 秒内完成增长,然后维持 15 秒,再在 10 秒内回落。这样更接近真实场景。
# 峰值测试的典型施压模式(示意)
# 前 60 秒:低负载,预热
# 第 61 秒:3 秒内压力暴涨到 10 倍
# 第 61-75 秒:维持峰值压力
# 第 76-85 秒:压力回落到正常水平
# 第 86-120 秒:观察系统恢复情况
# 有些工具支持直接配置这种模式
# 找不到的话,就自己写个自定义逻辑
好,现在把这四种类型放在一起看,你应该能感觉到各自的定位了:
| 测试类型 | 核心目标 | 压力特征 | 典型持续时间 | 我的常用工具 |
|---|---|---|---|---|
| 负载测试 | 验证系统能否承载预期压力 | 平稳递增,到目标值后维持 | 15-30 分钟 | Locust / JMeter |
| 压力测试 | 找到系统的崩溃点 | 持续递增,直到系统垮掉 | 取决于系统上限 | Locust + 自定义阶梯脚本 |
| 稳定性测试 | 验证长时间运行的可靠性 | 中等负载,持续运行 | 4-72 小时 | 自定义守护脚本 + Prometheus |
| 峰值测试 | 模拟流量突增场景 | 瞬间暴涨后回落 | 2-5 分钟(单轮) | wrk / 自定义脚本 |
我个人做压测方案时,会把这四类都规划进去。每个类型跑一轮,暴露的问题面向完全不同。
你不能只做负载测试就以为万事大吉。你也不能只做压力测试,因为那种极限场景在线上很少出现,但你的线上服务要跑一年呢——稳定性测试是更实际的考验。
你可能会问:这四个类型,是不是都得做一遍?
我的回答是:看你们服务的性质。如果是个内部工具,做负载测试和稳定性测试就够了。如果是个对外提供服务的 API,四类都得跑,一个都别省。压力测试帮你找到系统上限,峰值测试帮你应对突发的流量洪峰——这两个往往是线上事故的源头。