压力测试的四种核心类型

做接口压力测试,你首先得搞清楚一件事:你究竟想测什么?

很多人上来就拿着工具一顿猛压,压完一看报告——响应时间涨了,没报错,然后就交差了。这其实挺浪费的。我见过不少团队,压测报告写得花里胡哨,但核心问题一个都没暴露出来。

为什么会这样?说白了,就是没搞明白压力测试的分类。

我个人习惯把压测分成四类:负载测试、压力测试、稳定性测试和峰值测试。每一类都有它特定的目标,工具、场景、指标都不一样。你混着用,数据就变味儿了。

核心观点:测试类型的选择,决定了你能从压测中得到什么信息。选错了类型,再漂亮的数据也救不了你。

负载测试(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 / 自定义脚本

我个人做压测方案时,会把这四类都规划进去。每个类型跑一轮,暴露的问题面向完全不同。

你不能只做负载测试就以为万事大吉。你也不能只做压力测试,因为那种极限场景在线上很少出现,但你的线上服务要跑一年呢——稳定性测试是更实际的考验。

压力测试四种核心类型 · 知识体系 压力测试类型 负载测试 预期压力下的功能验证 15-30 分钟 压力测试 寻找系统崩溃点 持续递增至上限 稳定性测试 长期运行可靠性 4-72 小时 峰值测试 流量突增场景模拟 2-5 分钟/轮 关键提醒 四种类型各有侧重 不要用错场景 工具可以复用,方案必须定制 避坑指南 稳定性测试不能省 压力测试要有熔断保护 峰值测试要模拟真实曲线

你可能会问:这四个类型,是不是都得做一遍?

我的回答是:看你们服务的性质。如果是个内部工具,做负载测试和稳定性测试就够了。如果是个对外提供服务的 API,四类都得跑,一个都别省。压力测试帮你找到系统上限,峰值测试帮你应对突发的流量洪峰——这两个往往是线上事故的源头。