想象你是“满堂红”中餐厅的老板,下周要去参加城市美食节。美食节的规则很简单:上午 11 点到下午 2 点,客人不停涌入,你必须在三个小时内“接住”尽可能多的顾客,还要让他们吃得满意。你最担心什么?——厨房能不能扛住?平时一小时出 200 道菜,那天一小时来 1000 个客人,出菜速度是翻倍还是瘫痪?客人等多久会发火?要是同时来了 300 桌,是先乱成一锅粥,还是能稳住阵脚? 性能测试与压测,就是这场美食节之前的“带妆彩排”。软件系统就是你的餐厅,请求就是客人,服务器就是后厨。我们要做的,是提前用工具模拟“客人大批涌入”的场景,把系统推到极限边缘,观察它在什么情况下开始慢下来、报错、甚至崩溃,然后赶在真正的“美食节”(上线 / 大促)之前,把短板补上。这篇文章,我们会用“开餐厅”的视角,走完压测的完整旅程:先定目标、看指标,再选择测试类型与加压方式,定位瓶颈,最后给出扩容与工程化的落地建议。

岗位关联

掌握性能测试与压测,是软件与 AI 从业者从“能跑就行”走向“扛得住、稳得起”的关键一步——它能让你在生产事故之前发现问题,成为团队里最懂系统底牌的那个人。

目录
  1. 可视化演示
  2. 基本概念
  3. 核心指标
  4. 测试类型
  5. 加压方式
  6. 定位瓶颈
  7. 场景设计
  8. 容量规划
  9. 工程实践
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

展示系统处理流水线、实时性能指标曲线及多方案对比分析,包含数据流转、吞吐延迟监控与方案评估。

本节配有交互动效(进入视口后自动加载,约 3KB)。

系统可视化 处理流程:输入→处理→模型→输出 性能监控:实时指标 P=L×T

基本概念

要办美食节,你最先做的不是采购,而是问自己三个问题:目标接待多少人?客人最多愿意等多久?如果忙不过来能接受赔多少口碑?这就是性能测试的起点——不是等到系统卡了才去救火,而是带着明确目标做一场“带妆彩排”。在软件领域,这套“目标”被称为 SLA(服务等级协议),它约定了系统在特定并发下必须达到的响应时间与可用性。

性能测试的分类就像餐厅的三种演练方式:负载测试是模拟预计客流,验证“正常营业状态下达标没有”;压力测试是不断加人直到餐厅崩溃,找到“极限接待量在哪”;稳定性测试是让餐厅连续营业一周,看是否会出现慢性损耗。实施时机也遵循同样逻辑:大促前做压力演练,每周例行做负载回归,长期运行的服务则安排稳定性巡逻。

一个完整的压测过程不能一上来就满负荷,得给系统“热身”的时间。

回到餐厅视角:目标、分类、时机,这三件事就像美食节的“作战计划书”。有了它们,你才不会在当天手忙脚乱——压测不是压力本身,而是对压力的预演。

T总=T升温+T稳态+T回落\displaystyle T_{总} = T_{升温} + T_{稳态} + T_{回落}
这个公式把一次压测拆成三段:先让流量慢慢爬坡,再维持高负载观察,最后缓缓释放。就像美食节当天,客人不会瞬间坐满,而是陆续进店、高峰持续、再逐渐散去。
  1. 测试总时长一次压测从开始施压到结束的总时间,相当于美食节从开门到送走最后一位客人的完整营业周期。
    T总T_{总}
  2. 升温阶段并发数从零逐步爬到目标值的阶段,好比开店前半小时客人陆续入场,厨房逐步进入满负荷状态。
    T升温T_{升温}
  3. 稳态阶段维持目标并发持续观察的阶段,相当于中午 11 点到 2 点的高峰期,是发现问题的主要窗口。
    T稳态T_{稳态}
  4. 回落阶段并发数逐步释放直到归零,防止流量瞬间切走后引发连接池雪崩,就像闭店后错峰让客人离场。
    T回落T_{回落}

核心指标

判断餐厅经营得好不好,老板只需盯三个数字:出菜速度(每小时上几道菜)、等菜时间(顾客下单到上齐要多久)、同时就餐人数(餐厅里同时坐着几桌)。在压测里,这三个数字分别叫吞吐量、响应时间和并发数,它们是铁三角关系。

吞吐量(Throughput / TPS)是单位时间内系统处理完成的请求数,相当于厨房每小时端出的菜量;响应时间(Response Time)是单个请求从发出到收到完整响应的耗时,相当于顾客从点菜到上齐的等待;并发数(Concurrency)是同一时刻在途的请求数量,相当于餐厅内同时用餐的桌数。三者不是独立变量,而是被一条“铁律”锁定在一起的。

这个铁律来自排队论中的 Little 定律:

请记住这个铁三角:做压测时,你改变的是并发数(往餐厅里放人),但真正要观察的是吞吐量(出菜速度)和响应时间(等菜时长)。如果并发翻了十倍,吞吐没涨、响应却暴涨,说明厨房已经饱和了。

N=X×R\displaystyle N = X \times R
通俗说:餐厅里同时坐着的桌数(N),等于每小时翻台的桌数(X)乘以每桌平均用餐时长(R)。系统里同时处理的请求数,天然等于吞吐量乘响应时间——你没法只要其中一个而不影响另外两个。
  1. 并发数 N系统中同时存在的请求数,对应餐厅里正在就餐的桌数,是压测中直接控制的变量。
    NN
  2. 吞吐量 X每秒钟系统成功处理完的请求数量,对应厨房每秒钟真正端出菜的桌数。
    XX
  3. 响应时间 R每个请求从进入系统到完成所花的平均时间,对应每桌客人从点菜到吃完离开的平均时长。
    RR
  4. 乘法关系三者互相锁定。想提高吞吐又不延长响应,并发就必须跟着涨;反之,并发固定时,请求越慢,系统能处理的请求就越少。
    N=X×RN = X \times R

测试类型

餐厅有三种“体检”方式,对应三种测试类型。第一种是负载测试:今天预估来 500 桌客人,我就模拟 500 桌,看每桌等菜时间是否在承诺的 20 分钟内——这回答的是“达标没有”。第二种是压力测试:不管指标了,继续往店里放人,600、700、800 桌,直到客人掀桌、厨房瘫痪——这回答的是“上限在哪”。第三种是稳定性测试:每天保持 300 桌客流,连续跑一个月,看第 29 天是否出现内存泄漏、连接池枯竭这类慢性病——这回答的是“能扛多久”。

压力测试的核心机制可以用排队论中的利用率公式解释。当资源利用率接近 1 时,系统进入混沌状态;超过 1 时,请求开始排队堆积。

三种测试类型就像餐厅的三种体检,各司其职:负载测试保证今天的营业达标,压力测试探明极限在哪里,稳定性测试确保一个月后不会突然倒闭。真正成熟的压测体系,三张体检单都得做。

U=λμ\displaystyle U = \frac{\lambda}{\mu}
U 表示资源的忙碌程度。当顾客到达率 λ 逼近厨房服务率 μ 时,利用率接近 100%,后厨每时每刻都在连轴转,只要再来一个客人,队列就会无限拉长。
  1. 资源利用率 U服务器或后厨的忙碌比例,0 表示完全空闲,1 表示满负荷运转。
    UU
  2. 到达率 λ单位时间内新到达的请求数,对应客人进店的速率。
    λ\lambda
  3. 服务率 μ单位时间内系统最多能处理的请求数,对应厨房最大出菜速率。
    μ\mu
  4. 比值关系利用率等于到达率除以服务率。负载测试要求 U 长期低于某个安全值(如 0.7),压力测试则让 U 逼近甚至超过 1。
    U=λμU = \frac{\lambda}{\mu}

加压方式

确定了测试类型,下一步是“怎么把客人放进店里”。阶梯加压是最常用的方式:每 2 分钟放一拨客人,休息观察一会儿再放下一拨——就像餐厅每小时分三批放号入场,每批都比上一批多 30 桌。这样做的最大好处是能精准找到“拐点”:哪个批次开始出菜速度不再上涨,哪个批次开始客人排队抱怨。

另一种方式是恒定负载:从开门到关门,店里始终保持 300 桌客人,新客进、老客走,动态平衡。这模拟的是“持续稳定但从不冷场”的真实业务,最适合稳定性测试。还有一种是突发峰值:中午 12 点整瞬间涌入 500 桌,考验的不是平均能力,而是瞬时爆发和快速排队的容错能力,对应电商秒杀、抢票等场景。

阶梯加压的模型可以用一个分段函数来表达:

三种加压方式可以搭配使用:平时用阶梯加压摸清拐点,验证稳定性时用恒定负载,大促前再用突发峰值做一次“极限生存测试”。放客人的方式不同,你看到的问题也不同。

VU(t)=VU0+⌊tT⌋×VUstep\displaystyle \mathrm{VU}(t) = \mathrm{VU}_0 + \left\lfloor \frac{t}{T} \right\rfloor \times \mathrm{VU}_{step}
这个公式描述的是:每过 T 秒,并发用户数就往上跳一档。就像餐厅每 10 分钟放一批客人入座,每批新增 30 桌,直到放完为止。
  1. 当前并发 VU(t)t 时刻正在模拟的并发用户数,对应 t 时刻餐厅里的总桌数。
    VU(t)\mathrm{VU}(t)
  2. 初始并发 VU₀压测启动时的基础并发,相当于刚开店时已经预约好的 50 桌客人。
    VU0\mathrm{VU}_0
  3. 阶梯批号向下取整的除法结果,表示已经放行了几批客人,第几批决定了当前累计新增量。
    ⌊tT⌋\left\lfloor \frac{t}{T} \right\rfloor
  4. 单级增量 VU_step每一批新增的并发数,比如每 10 分钟放 30 桌;整个式子将级数乘以增量,得到累计并发。
    VUstep\mathrm{VU}_{step}

定位瓶颈

压测报告显示“系统扛不住了”,但问题到底出在哪个环节?是收银台算账太慢(CPU 密集型函数),还是传菜通道太窄(网络 / IO),又或者是库存系统扯后腿(下游依赖)?这就要用到“定位瓶颈”的三件套工具。

火焰图(Flame Graph)是第一种工具。它像一张“后厨工时分布图”:每个矩形条代表一个函数,宽度表示它占用的 CPU 时间。看到某个函数像一块巨大的红色砖头横在图上,瓶颈基本就锁定了。链路追踪(Distributed Tracing)是第二种工具,它给每个请求发一张“行程记录单”,记录它从进网关、过鉴权、查数据库到返回响应的每一站耗时——哪一站停留最久,哪里就是堵点。资源监控则是第三种,盯着 CPU、内存、磁盘、网络的利用率曲线,看资源是在压测开始后逐步耗尽还是瞬间打满。

瓶颈出现时,响应时间往往呈指数级恶化,这正是排队论中著名的“延迟爆炸”效应:

定位瓶颈就像检修餐厅:先用火焰图看后厨谁在磨洋工,用链路追踪还原客人完整的动线,再用资源监控确认是水电气哪一样供应不上。三管齐下,才能把“系统卡了”这种笼统的抱怨,变成“登录接口的加密函数占用 CPU 83%”这种可修复的结论。

R=R0×11−U\displaystyle R = R_0 \times \frac{1}{1 - U}
当资源利用率 U 接近 1 时,分母趋近于 0,响应时间被急剧放大。好比厨房利用率到 90% 时,不是只慢 10%,而是可能慢 10 倍——因为大家都在排队抢同一个灶头。
  1. 当前响应时间 R在给定负载下用户实际感受到的平均等待时间,即压测中测得的响应时间。
    RR
  2. 基础响应时间 R₀系统空闲状态下的响应时间,对应餐厅没有客人时的出菜速度,是性能的“底子”。
    R0R_0
  3. 利用率 U瓶颈资源(CPU、数据库连接等)当前的忙碌比例,来自前面利用率公式的结果。
    UU
  4. 放大因子1 除以 (1 − U)。U 从 0.5 涨到 0.9,因子从 2 变成 10,响应时间放大十倍;U 为 1 时因子无穷大,系统彻底无响应。
    11−U\frac{1}{1 - U}

场景设计

压测不是把“一大波请求”丢给系统就完事——真实世界里,客人不是一模一样的。有的点招牌菜,有的只点饮料;有的走会员通道,有的是新客注册。压测场景设计的第一原则,就是按真实业务比例编排脚本:登录占 10%、浏览菜单占 40%、下单占 30%、支付占 20%,并且这些操作之间的思考时间也要模拟真实用户。

第二个关键是数据准备。拿餐厅类比:如果用一套全是“番茄炒蛋”的菜单做压测,测出来的是缓存命中率极高的虚假性能;真实数据应该有热点商品、冷门商品、大客户订单、异常订单。压测数据要贴近生产环境的量级与分布,否则结果就像“用一张只有一道菜的酒席测后厨效率”。

第三个关键是环境隔离。压测流量不能和真实用户混在一起,就像美食节彩排不能惊扰正常营业的顾客。独立环境、独立数据库、独立缓存,才能保证压测数据的纯净性。而虚拟用户数的估算,遵循一个简单而实用的公式:

场景设计的本质是“真实”。真实的比例、真实的数据、真实的环境。用一张“只会做番茄炒蛋的菜单”来彩排美食节,测出的数字再漂亮,也替不了真正营业那天的鸡飞狗跳。

VU=TPS目标×R期望(秒)\displaystyle \mathrm{VU} = \mathrm{TPS}_{目标} \times R_{期望(秒)}
这是 Little 定律的反向应用:要达到每秒 500 单的目标吞吐(TPS),且期望单均耗时 2 秒,那么至少需要 1000 个虚拟用户同时在线模拟。
  1. 虚拟用户数 VU压测工具中需要启动的并发用户数,相当于你要往餐厅里放入的模拟客人数量。
    VU\mathrm{VU}
  2. 目标吞吐 TPS目标业务期望的每秒事务数,如大促期间每秒要接 500 单。
    TPS目标\mathrm{TPS}_{目标}
  3. 期望响应时间 R期望以“秒”为单位的平均响应时间目标,比如每笔下单要在 2 秒内完成。
    R期望(秒)R_{期望(秒)}
  4. 乘积关系两者相乘得到需要模拟的虚拟用户数。响应时间越大,为了维持同样的吞吐,需要越多的“在途”请求。
    VU=TPS目标×R期望(秒)\mathrm{VU} = \mathrm{TPS}_{目标} \times R_{期望(秒)}

容量规划

假设压测已经做完,你知道了餐厅的极限接待量是每小时 1000 道菜,但美食节当天预计会有 3000 位客人——接下来怎么办?这就是容量规划要回答的问题:缺多少产能、用什么方式补、补多少最经济。

容量评估是第一步:把系统的“单机容量”测出来,就像测出一名厨师一小时最多能出 30 道菜。预测模型给出业务峰值:根据历史曲线、活动排期、用户增长,预测美食节当天最高同时在线人数。扩容策略选择补产能的方式:加厨师(水平扩容,多开几个服务实例)还是换大厨(垂直扩容,升级 CPU 和内存),或者两者结合。

容量规划的计算思路,可以抽象为一个朴素公式:

容量规划是压测的“终点站”:压测不只是为了发现问题,更是为了回答“资源够不够”。算出台数、定好策略、留足冗余,美食节那天的厨房才能从容开火。

N实例=⌈Q峰值q单机×s⌉\displaystyle N_{实例} = \left\lceil \frac{Q_{峰值}}{q_{单机}} \times s \right\rceil
准备上线的服务器台数,等于“预测峰值流量 ÷ 单机最大承载量”,再乘上一个安全系数,最后向上取整。就像备食材:预估 1000 位客人,按每位 0.5 斤菜备料,再留 30% 富余,宁多勿缺。
  1. 实例数量 N实例需要准备的服务实例数,对应美食节要雇的总厨师人数。
    N实例N_{实例}
  2. 峰值流量 Q峰值预测模型给出的业务最高并发量,对应美食节当天同时到店的客人峰值。
    Q峰值Q_{峰值}
  3. 单机容量 q单机一台服务器经过压测验证的最大承载能力,对应一名厨师在高峰期的最大出菜数。
    q单机q_{单机}
  4. 安全系数 s预留的冗余缓冲(通常 1.2~1.5),用于吸收突发流量波动和单机故障,对应多备 20%~50% 的食材。
    ss
  5. 向上取整结果必须取整数,且只入不舍——差的半台机器,在真实高峰到来时可能成为压垮系统的最后一根稻草。
    ⌈⋅⌉\lceil \cdot \rceil

工程实践

如果压测只在每年大促前做一次,那就相当于餐厅只在美食节前才大扫除——平时积累的问题早就把系统拖垮了。真正的压测要融入日常研发流程,这就是工程实践的意义。

第一件事是CI 集成:把压测写进流水线,每次代码合并、每次发版,自动跑一轮轻量级性能回归,就像每次装修后都做水电验收。第二件事是性能回归:维护一份“黄金基线”,记录每次合入前后响应时间的变化率,如果某次提交让接口慢了 15%,构建就失败拦截,问题在合并前就被拦下来。第三件事是报告呈现:压测结果不能只丢出一堆数字,要输出一份让研发、测试、运维、老板都能看懂的“体检单”——哪里达标、哪里超限、风险等级是什么。

性能回归的判断标准,最终落在变化率上:

工程实践让压测从“一次性的考古”变成“日常的体检”。流水线里那道压测门禁,就像餐厅门口的等位时长显示屏——超出承诺就自动亮黄灯,提醒后厨赶紧加人。性能,从此成为被持续守护的底线,而不是上线后才追悔的遗憾。

Δ=R本次−R基线R基线×100%\displaystyle \Delta = \frac{R_{本次} - R_{基线}}{R_{基线}} \times 100\%
Δ 表示本次变更相对基线的性能变化。变化率超过团队约定的阈值(如 10%),流水线即判定为性能回归并阻断发布——就像每次改动菜单后都要试菜,口味退步超过一定幅度就不能上新。
  1. 性能变化率 Δ衡量本次改动让系统变快还是变慢的百分比,正数表示变慢,负数表示变快。
    Δ\Delta
  2. 本次响应时间 R本次合入本次代码后,压测得到的接口平均响应时间。
    R本次R_{本次}
  3. 基线响应时间 R基线历史上记录的基准响应时间,通常取上一次稳定发布的压测结果。
    R基线R_{基线}
  4. 百分比转换两者之差除以基线再乘 100,得到可读的变化百分比,便于设定统一的报警阈值。
    ×100%\times 100\%

AI 应用场景

大促前的容量评估

阶段:性能测试与容量规划

解决的问题:电商平台每次大促前都需要确认系统能否承接预估流量。传统方式是凭经验粗略估算服务器台数,要么过度采购造成浪费,要么低估流量导致宕机。通过压测建立“并发数—吞吐量—响应时间”的容量模型,再结合历史流量预测峰值,可以精准算出所需实例数。

具体案例:某电商平台在双 11 前,用压测工具按业务比例(浏览 50%、加购 20%、下单 20%、支付 10%)构建测试脚本,在预发环境逐步加压到预估峰值的 1.5 倍,发现订单服务的数据库连接池在 80% 利用率时响应时间急剧恶化,据此提前扩容并优化连接池参数,大促当天核心接口 P99 响应时间稳定在 300ms 以内。

微服务架构的瓶颈定位

阶段:瓶颈定位与性能分析

解决的问题:微服务架构中一次请求要经过网关、多个服务、数据库、缓存,传统排查方式只能逐个服务看日志,效率极低。利用火焰图分析 CPU 热点,结合链路追踪还原完整调用链,能快速定位到底是哪个服务、哪个数据库查询拖慢了整体响应。

具体案例:某金融科技公司在一次压测中发现支付接口响应时间从 200ms 涨到 2s。通过链路追踪发现耗时集中在“账户服务”调用“风控服务”的环节,火焰图进一步定位到风控服务中的规则引擎正则匹配占用 76% CPU,优化匹配算法后响应时间恢复到 250ms。

CI 流水线中的性能回归门禁

阶段:工程实践与自动化测试

解决的问题:功能迭代频繁引入性能劣化,上线后才发现“上周还很快,这周变慢了”。把轻量级压测脚本集成到 CI 流水线,每次合并前自动跑一轮基线对比,性能变化率超过阈值直接拦截构建,把性能问题堵在合入之前。

具体案例:某在线教育团队在 GitLab CI 中加入压测阶段:每次合并请求触发 3 分钟的冒烟压测,对比基线库中同接口的 P95 响应时间,若变化率超过 10% 则流水线失败。上线半年来,成功拦截了 7 起因新增慢 SQL 或循环依赖导致的性能回退,性能事故率下降 80%。

Python 演示

python43 行
import random  def simulate_queue(arrival_rate, service_rate, duration=100):    """模拟一个 M/M/1 排队系统:餐厅顾客到达与服务"""    time = 0.0    in_service = False    total_wait = 0.0    finished = 0    queue = []    next_arrival = random.expovariate(arrival_rate)    next_service_end = float("inf")     while time < duration:        next_event = min(next_arrival, next_service_end)        time = next_event        if time > duration:            break        if next_event == next_arrival:            queue.append(time)            next_arrival = time + random.expovariate(arrival_rate)            if not in_service:                next_service_end = time + random.expovariate(service_rate)                in_service = True        else:            start = queue.pop(0) if queue else time            total_wait += time - start            finished += 1            if queue:                next_service_end = time + random.expovariate(service_rate)            else:                in_service = False                next_service_end = float("inf")    return finished, finished / duration, (total_wait / finished) if finished else 0  if __name__ == "__main__":    service_rate = 5.0  # 厨房每秒能服务 5 个顾客    print("到达率 | 吞吐量 | 平均响应(s)")    for arrival in [1, 2, 3, 4, 4.5, 4.8, 5.0, 5.5]:        finished, tps, wait = simulate_queue(arrival, service_rate)        print(f"{arrival:4.1f}  | {tps:5.2f} | {wait:6.2f}")    print("结论:到达率越接近服务率,排队越长、响应越慢——这就是压测中的饱和效应")
目的:用排队论模拟餐厅压测,观察到达率逼近服务率时吞吐量与响应时间的饱和变化,直观复现正文中 Little 定律和利用率公式的行为。
  1. queue.append(time)顾客到达先入队,对应真实系统中请求进入待处理队列。
  2. next_arrival = time + random.expovariate(arrival_rate)泊松到达过程,模拟真实世界的随机客流。
  3. total_wait += time - start累计每个顾客从进店到被服务完的等待时间,用于计算平均响应时间。
  4. finished / duration用完成数除以总时长,得到吞吐量(TPS),即每秒真正处理完的请求数。
  5. random.expovariate(service_rate)指数分布的服务时间,对应厨房处理每道菜的耗时波动。

常见误区

误区“压测嘛,不就是一直加压力,加到系统挂了为止?不崩的压测都不算数。”

正解压力测试只是压测的一种类型,目的是探明上限;而日常更常见的是负载测试(验证达标)和稳定性测试(验证耐久)。把系统压崩只是手段之一,不是目的。就像餐厅彩排,不是非要把厨房烧了才知道极限在哪——用阶梯加压找到“出菜速度不再增长”的拐点就够了。每轮压测都往死里压,既浪费时间,又把系统置于无谓的风险中。

为何常见:很多人把“压力测试”当成性能测试的代名词,加上网上流传的“压测就是测极限”的说法,导致以崩溃论英雄。

误区“压测时并发数设得越高,说明系统越强,我就设 10 万并发!”

正解并发数是 Little 定律中的结果变量,不是可以随意拍脑袋的输入。系统的并发承载能力由吞吐量和响应时间共同决定:一个每秒只能处理 100 个请求、平均耗时 2 秒的系统,天然只能维持约 200 并发。盲目设置 10 万并发,只是在制造大量队列堆积和超时,测出的不是系统能力,而是垃圾请求堆积的速度。正确做法是从业务峰值反推需要多少并发,再逐步加压验证。

为何常见:把“并发数”误解为“同时打开的连接数”或者“在线人数”,忽视了它和吞吐、响应时间之间的约束关系。

误区“压测报告显示平均响应时间只有 300ms,完全达标,系统没问题!”

正解平均值会掩盖长尾问题。如果 P99 响应时间是 5 秒,意味着 1% 的用户体验极差——在千万级流量的系统里,这 1% 就是 10 万被惹恼的顾客。压测必须同时关注 P95、P99、P999 分位值,正如餐厅不能只看“平均等餐 5 分钟”,还要看到高峰期最倒霉的那桌客人等了 40 分钟。

为何常见:人类天然习惯用平均数概括整体,而性能数据往往是偏态分布,少数慢请求会严重拉高均值,分位值比均值更能反映真实体验。

误区“生产环境配置最真实,直接在上面压不就最准吗?省得搭一套环境。”

正解在生产环境压测会带来真实用户受影响的风险:压测请求打满数据库连接池,线上用户下单就会超时;测试数据污染生产库,还可能引发资损。正确做法是在独立压测环境复刻生产的部署架构与数据规模,或使用生产环境的影子流量在低峰期小范围验证。就像餐厅彩排不能在正常营业的餐桌上进行,需要闭店后或者用包间隔离演练。

为何常见:“生产最真实”的直觉是对的,但忽略了压测的破坏性。环境接近真实固然重要,但前提是隔离安全边界。

面试题

Q1. 在性能测试中,“吞吐量”最准确的含义是什么?

单选题 · easy

  • A.系统每秒处理完成的请求数量← 正确答案
  • B.系统同时建立的连接数量
  • C.网络带宽的占用大小
  • D.压测工具发送请求的总数

答案:A。吞吐量是单位时间内系统真正处理完成的请求数,相当于厨房每秒真正端出锅的菜量。B 是并发连接数,C 是带宽概念,D 是发送总量而不是“完成”量,都不符合吞吐量的定义。

Q2. 根据 Little 定律 N = X × R,当吞吐量固定时,平均响应时间越短,系统能维持的并发数会怎样变化?

单选题 · easy

  • A.越短则并发数越高← 正确答案
  • B.越短则并发数越低
  • C.保持不变
  • D.先涨后跌

答案:A。N = X × R 中 X 固定时,R 越小 N 越小。类比餐厅:每小时翻台 100 桌固定时,每桌吃 1 小时,店里同时只有 100 桌;每桌只吃 30 分钟,店里同时就只有 50 桌。处理得快,单位时间积压的在途请求自然就少。

Q3. 下列哪些属于性能测试的核心指标?

多选题 · mid

  • A.吞吐量(TPS)← 正确答案
  • B.响应时间(P95 / P99)← 正确答案
  • C.资源利用率(CPU / 内存)← 正确答案
  • D.代码注释覆盖率

答案:ABC。吞吐量衡量处理能力,响应时间衡量体验,资源利用率衡量系统饱和度,三者构成压测铁三角。代码注释覆盖率属于静态代码质量范畴,与运行时性能无关。

Q4. 压力测试最主要的目的是什么?

单选题 · mid

  • A.验证系统在预期负载下是否满足 SLA
  • B.探索系统容量上限并定位崩溃点← 正确答案
  • C.验证系统长时间运行的稳定性
  • D.测试系统接口的功能正确性

答案:B。压力测试是不断增大压力直到系统出问题,探明“极限在哪里”。A 是负载测试的目标,C 是稳定性测试的目标,D 是功能测试的目标。三类测试各管一段,压力测试专门回答“上限在哪”。

Q5. 阶梯加压策略最主要的好处是什么?

单选题 · mid

  • A.能在最短时间把系统打满
  • B.逐级增加负载,便于观察每个并发档位下的拐点← 正确答案
  • C.减少压测工具的资源消耗
  • D.避免产生任何错误请求

答案:B。阶梯加压像餐厅分批放号入场,每放一批观察一次出菜和排队情况,能精准定位“从哪一档开始吞吐不再增长、响应开始恶化”。A 是瞬间加压的特点但不利于观察拐点;C、D 与阶梯加压的核心目的无关。

Q6. 定位系统瓶颈时,常用的手段包括哪些?

多选题 · mid

  • A.火焰图分析 CPU 热点← 正确答案
  • B.链路追踪还原请求全路径耗时← 正确答案
  • C.监控 CPU / 内存 / 磁盘等资源水位← 正确答案
  • D.静态代码审查注释规范

答案:ABC。火焰图看函数级耗时,链路追踪看跨服务全链路耗时,资源监控看硬件水位,三者结合才能锁定瓶颈。静态代码审查审查的是代码风格与规范,不用于运行时瓶颈定位。

Q7. 某系统基础响应时间为 50ms,资源利用率达到 90% 时,根据 R = R₀ × 1/(1−U),当前平均响应时间约为多少?

单选题 · extreme

  • A.55ms
  • B.100ms
  • C.500ms← 正确答案
  • D.1000ms

答案:C。将 U = 0.9 代入公式,放大因子为 1/(1−0.9) = 10,50ms × 10 = 500ms。利用率 90% 时响应时间不是“慢 10%”,而是慢 10 倍——这正是排队论中延迟爆炸效应。餐厅厨房忙到 90% 时,新客人的等待时间会急剧拉长。

Q8. 进行压测场景设计时,以下哪项最值得优先关注?

单选题 · mid

  • A.按真实业务比例编排压测脚本← 正确答案
  • B.把并发数设置得越稳妥越好
  • C.只测一个最简单接口
  • D.使用测试环境的最小数据集

答案:A。压测场景必须还原真实业务的比例、数据量和依赖关系,才具有参考价值。B 并发数应由业务峰值推导;C 只测简单接口会掩盖真实链路瓶颈;D 使用最小数据集会得出虚假的高性能,因为缓存命中和数据量都会影响结果。

Q9. 容量规划时,计算所需实例数需要考虑哪些输入?

多选题 · hard

  • A.预测的业务峰值流量← 正确答案
  • B.单台实例的压测容量数据← 正确答案
  • C.预留的安全冗余系数← 正确答案
  • D.前端页面的配色方案

答案:ABC。容量规划公式 N = ⌈(Q峰值 / q单机) × s⌉ 需要三个输入:峰值流量预测、单机容量实测、安全系数。峰值越高需要实例越多,单机能力越强所需越少,安全系数提供缓冲。前端配色与容量计算无关。

Q10. 稳定性测试的核心特征是什么?

单选题 · easy

  • A.在极短时间压到系统崩溃
  • B.保持恒定负载长时间运行,观察是否有慢性问题← 正确答案
  • C.只测试系统的登录接口
  • D.在功能测试通过后就不再执行

答案:B。稳定性测试以恒定负载长时间运行,专门暴露内存泄漏、连接池耗尽、日志堆积等“慢性病”。A 是压力测试的特征;C 只测单一接口不是稳定性测试的范畴;D 将稳定性测试与功能测试混为一谈,稳定性测试恰恰要持续执行。