上线前跑了一轮压测,报告上写着「单机 QPS 3000,P99 85ms」,大家看了都很安心。结果放量那天,真实流量才到设计容量的一半,接口就开始大面积超时,数据库连接池被打满,缓存命中率断崖式下跌。事后复盘发现,那份看起来很漂亮的压测报告,测的根本不是线上那套系统——它是「一份数字」,不是「一次验证」。
性能压测最大的误区,是把它当成一次「交作业」:跑个脚本、拿到数字、写进文档,然后就结束了。真正有价值的压测,是要回答一个具体问题——「在什么条件下,这个系统会先坏,坏在哪里」。这篇文章聊聊把压测做成有效验证的三层做法。

第一层:先想清楚要回答什么问题,再动手写脚本
很多人拿到压测任务的第一反应是:找压测工具、写脚本、设个并发数、开跑。但如果没有事先想清楚「我要验证什么」,跑出来的数字基本没有意义。
压测通常要回答三类问题,对应三种完全不同的测试目标。第一类是容量验证:系统到底能扛多少?这类测试要的是「找到拐点」——把并发逐步往上加,观察 QPS 什么时候不再随并发增长(说明到达瓶颈),同时观察响应时间在哪个点开始陡增。第二类是稳定性验证:系统能不能长时间稳住?这类测试重点是持续施压几小时甚至几十小时,看有没有内存泄漏、连接泄漏、慢查询累积、日志把磁盘写满这类「时间维度才会暴露」的问题。第三类是瓶颈定位:在已知会崩的场景下,最先撑不住的是哪一环?
这三类目标对应的脚本设计、施压曲线、观测指标完全不同。容量验证要的是阶梯式加压,稳定性验证要的是恒定压力长跑,瓶颈定位可能要叠加多种流量混合。很多团队压测没意义,就是因为用一套「固定并发跑十分钟」的脚本,去回答所有问题——那只能得到一组无法解释的数字。
另一件必须先想清楚的事是流量模型。真实流量从来不是均匀的:有热点数据(少数商品被反复访问)、有读写比例、有请求大小的长尾分布。如果压测脚本里用的是一批均匀随机生成的 ID,缓存命中率会接近 100%,测出来的性能自然好得离谱——而线上热点一旦过去,命中率掉下来,性能立刻原形毕露。所以脚本里的测试数据必须尽量「像真的」:带热点、带分布、带真实读写比例。
第二层:让压测环境尽量接近线上,并且明确差异在哪
「压测环境不是线上环境」这句话人人会说,但关键在于:你要知道差异会往哪个方向影响结论,而不是笼统地说「参考价值有限」。
最常见的差异是数据量级。测试库里可能只有几万条数据,而线上有几千万条。数据量小的时候,索引可能全在内存里,查询几乎不落盘;数据量一大,同样的查询就会因为磁盘 IO 而慢一个数量级。所以压测前要把数据量灌到和生产同一量级——哪怕只灌主表,也比拿一个小库测出来的数字可信。
其次是依赖组件的真实度。数据库、缓存、消息队列、下游第三方接口,是压测中最容易被「mock 掉」的部分。mock 掉下游确实能让压测更稳定,但如果被 mock 的恰恰是线上的瓶颈(比如那个第三方的鉴权接口本来就要 80ms),测出来的结果就是自欺欺人。折中做法是:对不关心的下游用 mock,对怀疑是瓶颈的下游一定接真实或至少做等价的延迟注入。
还有网络拓扑和实例规格。压测机和应用服务器是否同机房、是否有负载均衡、实例 CPU/内存是否一致,这些都会影响数字。最麻烦的是「压测机自己先成为瓶颈」——用的是同一台机器一边压一边被压,CPU 早就被压测客户端吃满了,测出来的所谓「系统上限」其实是压测机自己的上限。压测机应当独立,且要有足够余量,同时全程监控压测机自身的资源占用。
把这些差异列成一张表,明确标注「本次压测与线上的已知差异,以及各自影响的方向」,比在报告里堆一堆漂亮数字有用得多。

第三层:看数字,更要看数字背后的链路
压测报告上如果只有 QPS、平均响应时间、P99 这几个数,那基本没法用来做决策。真正能支撑决策的,是「这些数字是怎么来的」。
第一件事是分位数,而不是平均值。平均值会掩盖问题:如果 90% 的请求 10ms 返回、10% 的请求 2 秒返回,平均下来是 209ms,看着还行,但那 10% 的用户体验非常糟糕。所以 P95、P99、P999 比平均值重要得多,尤其要关注 P99 随并发增长的曲线——它通常在某个点开始垂直上升,那个点就是系统的实际容量边界。
第二件事是同时观测全链路指标。压测期间,除了压测工具给出的响应指标,还要同步看应用侧的 CPU、内存、GC 频率与停顿、线程池队列长度;数据库侧的连接数、慢查询数、锁等待;缓存侧的命中率、大 key 数量;中间件的队列积压。只有把这些放在同一时间轴上对照,才能看出「QPS 掉下来的那一刻,是数据库连接池先满了,还是 GC 停顿先变长了」。
第三件事是做对照实验。发现瓶颈后,不要急着下结论,改一个变量再压一次:怀疑是连接池太小,就把连接池调大再跑;怀疑是某条慢 SQL,就把它优化掉再跑。同样的流量下,指标有没有实质改善,才是判断瓶颈定位是否准确的唯一标准。很多所谓的「性能优化」是在没有对照实验的情况下做的,改完了也不知道到底是谁起了作用。
最后,压测的产出不应该是「一份报告」,而应该是「一组结论和一份预案」:系统在什么负载下开始劣化、最先劣化的是什么、降级开关在哪里、扩容需要多久。这样等到真实流量上来时,团队手里有地图,而不是只有一张过去的照片。

结语
压测的本质不是「测出一个数」,而是「提前把系统推向极限,看它在哪里坏、怎么坏」。一份可信的压测报告,应该让人看完之后能回答:我们的容量边界在哪里,瓶颈是什么,超过边界会怎样退化。
如果一份报告只留下一堆漂亮的数字,却回答不了任何决策问题,那它顶多算一次「性能演示」,不是一次「性能验证」。而演示和验证之间的差距,往往就是上线当晚的从容与手忙脚乱之间的差距。