性能测试培训 · 基础篇
核心概念 + 理论基础 · 建立完整的性能测试知识体系
1. 为什么要做性能测试?
1.1 餐厅比喻:从生活理解性能测试
📖 想象你开了一家餐厅
平时每天来 10 个客人,一切运转正常。但你准备花 50 万投广告,预计引来 1000 人。在花钱之前,你需要搞清楚:
| 餐厅的问题 | 对应系统指标 | 不解决的后果 |
|---|---|---|
| 厨房能不能同时出这么多菜? | 服务器处理能力(CPU / GPU) | 出菜速度慢,客人等太久走了 |
| 座位够不够? | 连接数 / 内存 / 线程池 | 客人进不来,在门口排队 |
| 传菜的人够不够? | 网络带宽 / IO 能力 | 菜做好了送不出去 |
| 菜单系统会不会卡死? | 数据库 / 缓存性能 | 点单系统崩溃,全店停摆 |
| 长时间高峰运转后厨房会不会出问题? | 系统稳定性 / 内存泄漏 | 运行几小时后系统越来越慢 |
| 突然涌入 500 人会不会直接瘫痪? | 峰值承受能力 | 系统直接崩溃,全部用户受影响 |
性能测试就是"提前模拟这 1000 个客人来你店里"——在真正花钱投广告之前,先验证你的餐厅(系统)能不能扛住。
1.2 真实世界的惨痛案例
⚠️ 案例一:双十一电商崩溃
某电商平台大促前未做充分压测。零点开抢时流量是平时的 50 倍,数据库连接池瞬间耗尽,商品页面全部 502。10 分钟内损失超过 2000 万元订单。事后分析发现,瓶颈在于数据库连接池只配了 100 个连接,而峰值需要 500+。一个配置参数,2000 万的教训。
⚠️ 案例二:12306 春运抢票
早年春运期间,12306 网站频繁崩溃,一度成为全民吐槽的对象。根本原因是系统架构未针对高并发设计——几亿人在同一时刻发起查询和抢票请求。后来引入排队机制、CDN 加速、弹性扩容,才逐步改善。这个案例说明:性能问题不仅是技术问题,更是品牌和信任问题。
⚠️ 案例三:游戏开服崩溃
某热门手游首发上线,服务器开放注册后 30 秒内涌入 50 万玩家。登录服务器直接宕机,排队动辄 3 小时以上。社交媒体上差评如潮,应用商店评分从 5 星暴跌到 1.5 星。即便后续紧急扩容修复,首批用户已大量流失,游戏生命周期被严重缩短。
⚠️ 案例四:AI 应用上线翻车
某企业上线了一个内部 AI 助手,接入了大模型 API。上线第一天,全公司 200 人同时试用。由于没有做限流和排队,200 个并发请求直接打到第三方大模型 API,触发 Rate Limit(429 错误)。系统没有做降级处理,直接把 429 错误抛给了用户。结果:用户看到一堆"服务不可用"的报错,对 AI 助手失去信心,项目被领导叫停。
1.3 性能测试的 ROI 分析
很多团队觉得"性能测试太费时间",但我们来算一笔账:
| 项目 | 不做性能测试 | 做了性能测试 |
|---|---|---|
| 测试投入 | 0 人天 | 5-10 人天 |
| 上线后崩溃概率 | 高(30%+) | 低(<5%) |
| 崩溃后损失 | 直接损失 10w-1000w+ | — |
| 紧急修复成本 | 团队通宵 + 回滚 + 善后 | — |
| 用户信任损失 | 不可量化,但影响深远 | — |
| 品牌声誉影响 | 社交媒体负面传播 | — |
✅ 结论
性能测试的成本是确定的、可控的(几个人天);不做性能测试的风险是不确定的、可能巨大的。从 ROI 角度看,性能测试是一项"保险投资"——花小钱防大灾。
课堂练习
**练习 1:**列出你所知道的 3 个因为性能问题导致业务损失的真实案例(可以是你经历过的、新闻报道的、或同行分享的)。对每个案例分析:
- 性能问题的根本原因是什么?
- 如果提前做了性能测试,能否避免?
- 这次故障造成了什么层面的损失?(金钱 / 用户 / 品牌 / 信任)
2. 性能测试的价值与目标
2.1 性能测试不是"压爆系统"
💡 常见误解
"性能测试就是开一堆并发把系统搞崩,看它什么时候挂。"——这只对了一小部分。
性能测试的本质是:找到系统的能力边界,验证它能否满足业务需求。 更准确地说,性能测试要回答的问题是:
- 系统在预期负载下,能否正常提供服务?
- 系统的天花板在哪里?离目标还有多少余量?
- 如果超过天花板,系统会怎样表现?是优雅降级还是直接崩溃?
- 系统的瓶颈点在哪里?如何优化?
- 优化之后,效果如何?
2.2 性能测试的 5 个核心目标
| 目标 | 说明 | 典型场景 |
|---|---|---|
| 容量规划 | 搞清楚当前系统能扛多少量,需要多少机器才能支撑目标流量 | 大促前评估是否需要扩容、新产品上线前的资源规划 |
| 瓶颈识别 | 找到限制系统性能的最薄弱环节 | QPS 上不去,通过压测发现是数据库连接池只有 20 个 |
| 回归验证 | 版本迭代后,验证性能没有退化 | 新版本上线前,对比上个版本的性能基线 |
| SLA 验证 | 验证系统是否满足对外承诺的性能指标 | 合同要求 99.9% 可用性、P99 < 1s |
| 风险发现 | 发现隐藏的性能隐患(内存泄漏、连接泄漏、死锁等) | 稳定性测试跑 8 小时后发现内存持续增长 |
2.3 不同角色关心什么?
同一份性能测试报告,不同角色关注的重点完全不同:
| 角色 | 核心关注点 | 想看到的数据 |
|---|---|---|
| 开发工程师 | 瓶颈在哪?是我的代码问题还是基础设施问题? | 慢查询日志、CPU Profile、火焰图、GC 日志 |
| 运维 / SRE | 需要多少机器?什么时候需要扩容? | 资源利用率、容量水位线、扩容后的线性度 |
| 产品经理 | 用户体验如何?页面会不会卡? | 响应时间、首屏加载时间、交互延迟 |
| 技术负责人 | 能不能上线?风险在哪? | 是否达标、风险点清单、优化建议 |
| 老板 / 管理层 | 需要花多少钱?投入产出比如何? | 机器成本、扩容预算、故障预防价值 |
📖 写测试报告时的技巧
一份好的性能测试报告应该有"多层视图":摘要给老板看(结论 + 成本),详细数据给开发和运维看(指标 + 瓶颈分析),用户体验数据给产品看(RT + 成功率)。
课堂练习
**练习 2:**假设你负责一个电商 App 的性能测试,即将迎来周年庆大促。请回答:
- 你的性能测试核心目标是上述 5 个中的哪几个?为什么?
- 你需要向哪些角色汇报测试结果?每个角色最想听到什么?
- 如果老板问"需不需要花 10 万买更多服务器",你怎么用性能测试数据来回答?
3. 性能指标全解析
3.1 三种"用户数"的区别
很多人混淆"并发用户"和"在线用户",这两个概念差距非常大:
| 概念 | 定义 | 举例 | 数量级关系 |
|---|---|---|---|
| 注册用户数 | 系统中所有注册过的用户 | 100 万注册用户 | 最大 |
| 在线用户数 | 某一时刻登录状态的用户(可能在发呆、浏览,不一定在发请求) | 5 万在线 | 注册的 5-10% |
| 并发用户数 | 某一时刻正在向服务器发请求并等待响应的用户 | 500 并发 | 在线的 5-15% |
💡 关键理解
100 万注册用户 ≠ 要压测 100 万并发。真正的并发用户可能只有几百到几千。搞清楚这个区别,是避免"过度压测"或"不足压测"的第一步。
示例
一个社交 App,注册用户 200 万,日活 20 万(DAU),高峰期在线 5 万人。这 5 万人中,同一秒钟真正在点按钮、刷页面的大约 2000 人。所以压测目标应该是 2000-3000 并发,而不是 200 万。
3.2 QPS vs TPS vs RPS
| 指标 | 全称 | 含义 | 使用场景 |
|---|---|---|---|
| QPS | Queries Per Second | 每秒处理的查询数(通常指读请求) | 搜索引擎、API 网关、CDN 等以读为主的场景 |
| TPS | Transactions Per Second | 每秒处理的事务数(一个事务可能包含多个请求) | 电商下单(下单 = 查库存 + 扣款 + 创建订单 + 发消息) |
| RPS | Requests Per Second | 每秒处理的请求数(最通用的叫法) | 通用场景,与 QPS 含义接近 |
它们的关系
大部分情况下 QPS ≈ RPS,可以互换使用。TPS 通常 ≤ QPS,因为一个事务可能包含多个查询。 例如:用户下单一次 = 1 TPS,但后端可能产生 5 个 API 调用 = 5 QPS。
3.3 响应时间(Response Time)
响应时间 = 用户从发出请求到收到完整响应的总耗时。它由三部分组成:
网络传输时间 → 排队等待时间 → 服务端处理时间 → 总响应时间 (RT)
| 组成部分 | 含义 | 影响因素 |
|---|---|---|
| 网络时间 | 请求和响应在网络上传输的时间 | 物理距离、带宽、CDN、DNS 解析 |
| 排队时间 | 请求到达服务器后,等待被处理的时间 | 并发量、线程池大小、连接池容量 |
| 处理时间 | 服务器真正执行业务逻辑的时间 | 代码效率、数据库查询、外部调用 |
💡 常见误区
误区 1:"响应时间慢一定是服务器性能差"——不一定,可能是网络慢,也可能是压测机和被测服务器跨区域部署。 误区 2:"低并发时 RT 正常就行"——低并发时排队时间≈0,一切看起来都很快。高并发时排队时间暴增,RT 才会暴露真实问题。
3.4 吞吐量(Throughput)
**定义:**单位时间内系统成功处理的请求数或数据量。 两种表达方式:
- **请求维度:**每秒处理 200 个请求 = 200 QPS
- **数据维度:**每秒传输 50MB 数据 = 50 MB/s
计算公式:
吞吐量 = 成功请求数 / 总时间
举例:10 分钟内处理了 120,000 个成功请求
吞吐量 = 120,000 / 600秒 = 200 QPS常见误区
"吞吐量越高越好"——不一定。如果错误率很高,那吞吐量高可能只是因为大量请求快速失败(失败返回很快)。吞吐量必须结合错误率和响应时间一起看。
3.5 错误率(Error Rate)
**定义:**失败请求数占总请求数的比例。
错误率 = 失败请求数 / 总请求数 × 100%
举例:10,000 个请求中有 50 个返回 5xx 错误
错误率 = 50 / 10,000 = 0.5%关注哪些错误:
HTTP 5xx:服务端内部错误(最严重)HTTP 429:被限流(不一定是 bug,但影响用户体验)Timeout:请求超时(说明服务端处理太慢)Connection Refused:服务端拒绝连接(通常是连接池耗尽)
⚠️ 红线参考
- 核心业务接口:错误率 > 0.1% 需要关注,> 1% 禁止上线
- 非核心接口:错误率 > 1% 需要关注,> 5% 需要修复
3.6 拐点(Inflection Point)
**定义:**随着并发数增加,系统性能从"正常"急剧变为"异常"的那个临界点。 具体表现为:
- 响应时间突然大幅上升(例如从 200ms 突然跳到 2s)
- 吞吐量不再增长甚至开始下降
- 错误率开始明显上升
示例
**场景:**逐步增加并发用户数,记录每一级的指标:
| 并发数 | QPS | P95 RT | 错误率 | 状态 |
|---|---|---|---|---|
| 50 | 180 | 120ms | 0% | 正常 |
| 100 | 340 | 150ms | 0% | 正常 |
| 200 | 580 | 200ms | 0.1% | 正常 |
| 300 | 620 | 450ms | 0.5% | 接近拐点 |
| 400 | 600 | 1200ms | 3% | 超过拐点 |
| 500 | 480 | 3500ms | 12% | 严重过载 |
| 本例中,拐点在 200-300 并发之间。300 并发时 QPS 增长明显放缓、RT 翻倍、错误率开始上升。 |
3.7 瓶颈(Bottleneck)
**定义:**限制系统整体性能的最薄弱环节。就像木桶理论——最短的那块板决定了整个桶能装多少水。 常见瓶颈分布:
| 瓶颈位置 | 典型表现 | 诊断方式 |
|---|---|---|
| CPU | CPU 利用率 > 85%,其他资源都很空闲 | top 、CPU Profile、火焰图 |
| 内存 | OOM 错误、频繁 GC、Swap 使用量高 | 内存监控、Heap Dump 分析 |
| 磁盘 IO | IO Wait 高、磁盘读写延迟大 | iostat 、数据库慢查询 |
| 网络 | 带宽打满、TCP 连接数接近上限 | iftop 、 netstat |
| 数据库 | 连接池耗尽、大量慢查询、锁等待 | 慢查询日志、连接池监控 |
| 外部依赖 | 第三方 API 响应慢或限流 | 链路追踪(Tracing) |
💡 最容易误判的情况
CPU 只有 30%,内存也很空,但 QPS 就是上不去。很多人以为"服务器还很空闲",实际上线程都在等待 IO(等数据库返回、等外部 API)。这种情况下 CPU 不忙不代表没有瓶颈——瓶颈在 IO,不在计算。
课堂练习
**练习 3:**一次压测得到以下数据,请计算各项指标:
压测持续时间:10 分钟(600 秒)
总发送请求数:180,000
成功请求数:178,200
失败请求数:1,800
总响应时间之和:36,000,000 ms(所有请求的 RT 加起来)
请计算:
1. 吞吐量(QPS)= ?
2. 错误率 = ?
3. 平均响应时间 = ?
4. 如果 P99 响应时间是 1200ms,这意味着什么?4. 百分位数深入理解
4.1 为什么不能用平均值?
⚠️ 平均值的陷阱
假设 10 个请求的响应时间分别是: 100ms, 100ms, 100ms, 100ms, 100ms, 100ms, 100ms, 100ms, 100ms, 5000ms 平均值 = 590ms——看起来还不错。 但实际上 9 个人的体验是 100ms(优秀),1 个人的体验是 5000ms(极差)。 平均值完全掩盖了那 1 个人的痛苦。
更极端的例子:
示例
某服务的响应时间数据(1000 个请求):
- 950 个请求:100-200ms
- 40 个请求:500-800ms
- 9 个请求:2000-3000ms
- 1 个请求:30000ms(30 秒!) 平均值 ≈ 220ms——看起来很好。 **但现实是:**5% 的用户等了半秒以上,1% 的用户等了 2 秒以上,还有个别用户等了 30 秒。如果你每天有 100 万请求,那就是 1 万个请求超过 2 秒,100 个请求超过 30 秒。这些用户不会觉得"平均 220ms 挺快的",他们只记得那次 30 秒的等待。
4.2 百分位数的含义
| 百分位 | 含义 | 怎么理解 |
|---|---|---|
| P50 (中位数) | 50% 的请求在这个时间内完成 | "大多数人"的体验。代表典型用户感受 |
| P90 | 90% 的请求在这个时间内完成 | 只有 10% 的人比这更慢。常用的性能基准线 |
| P95 | 95% 的请求在这个时间内完成 | 只有 5% 的人比这更慢。中等严格的 SLO 目标 |
| P99 | 99% 的请求在这个时间内完成 | 只有 1% 的人比这更慢。严格的 SLO 目标 |
| P99.9 | 99.9% 的请求在这个时间内完成 | 千分之一的最差体验。金融/支付等高要求场景关注 |
4.3 图解:响应时间分布
请求数量
│
│ ████████████
│ █████████████████
│ ██████████████████████████
│ ████████████████████████████████████
│ █████████████████████████████████████████████
│ ████████████████████████████████████████████████████████
│ ████████████████████████████████████████████████████████████████
└──┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────→ 响应时间
50 100 150 200 300 500 800 1s 2s 5s
↑ P50 ↑ P90 ↑ P95 ↑ P99 ↑ P99.9
(120ms) (280ms) (500ms) (1.2s) (4.8s)
大部分请求集中在左侧(快),少数请求拖到右侧(慢)。
这条"长尾"就是百分位数要捕捉的。4.4 真实案例分析
⚠️ 案例:平均 RT 200ms,但 P99 是 5 秒
某电商搜索接口,平均响应时间 200ms,看起来很快。但 P99 是 5 秒。 这意味着什么?如果该接口每天被调用 1000 万次:
- 990 万次请求在 200ms 左右完成 ✅
- 10 万次请求超过 5 秒 ❌
- 这 10 万次请求背后是 10 万个真实用户,他们等了 5 秒以上才看到搜索结果
- 如果搜索是下单的前置步骤,这 10 万次慢请求可能导致 数千笔订单流失
4.5 如何选择关注哪个百分位?
| 业务场景 | 建议关注 | 原因 |
|---|---|---|
| 内部管理系统 | P90 | 用户数少、容忍度高,P90 够用 |
| 普通 C 端应用 | P95 | 平衡用户体验和工程成本 |
| 电商 / 社交 | P99 | 用户量大,1% 的慢请求 = 大量投诉 |
| 金融 / 支付 | P99.9 | 每笔交易都关系到钱,极端情况不可接受 |
| AI 对话 / 大模型 | P95(TTFT)+ P99(端到端) | TTFT 影响首字体验,端到端影响完整回答 |
课堂练习
**练习 4:**以下是某接口的响应时间数据(已排序),共 20 个请求:
50, 55, 60, 62, 65, 70, 75, 80, 85, 90,
95, 100, 110, 120, 150, 200, 350, 500, 1200, 8000 (单位: ms)- 计算平均值
- 找出 P50、P90、P95、P99
- 比较平均值和各百分位数,你发现了什么?
- 如果你是这个接口的负责人,你会重点关注哪个指标?为什么?
5. 并发与吞吐量的关系
5.1 三个阶段
随着并发用户数的增加,系统的吞吐量和响应时间会经历三个阶段:
| 阶段 | 并发区间 | 吞吐量 | 响应时间 | 系统状态 |
|---|---|---|---|---|
| 阶段一:线性增长区 | 低并发 | 随并发数线性增长 | 基本不变 | 资源充足,排队≈0 |
| 阶段二:饱和平台区 | 中等并发 | 增长放缓直至平台期 | 开始逐步上升 | 某个资源接近饱和 |
| 阶段三:过载下降区 | 高并发 | 反而下降 | 急剧上升 | 资源耗尽,大量排队/超时/错误 |
5.2 图解:经典三线图
吞吐量(QPS) 响应时间(RT) 错误率
│ │ │
│ ┌────── │ ╱ │ ╱
│ ╱ │ │ ╱ │ ╱
│ ╱ │ ╲ │ ╱ │ ╱
│ ╱ │ ╲ │ ╱ │ ╱
│╱ │ ╲ │ ╱ │ ──╱
└────────┼──────→ │ ╱ │ ───╱
并发 ↑ ↑ │╱ │───
最佳 最大 └──────────→ └──────────→
并发 并发 并发 并发
阶段一 阶段二 阶段三
(线性) (饱和) (过载)5.3 最佳并发点 vs 最大并发点
| 概念 | 定义 | 特征 | 实际意义 |
|---|---|---|---|
| 最佳并发点 (Optimal Point) | 吞吐量最高且响应时间仍在可接受范围内的并发数 | QPS 接近峰值、RT 增幅不大、错误率≈0 | 日常运行的目标并发数。线上负载应控制在此范围内 |
| 最大并发点 (Maximum Point) | 系统能勉强工作(不崩溃但勉强达标)的最大并发数 | QPS 开始下降、RT 大幅上升、错误率接近红线 | 系统的极限能力。仅在峰值短暂出现时可以接受 |
📖 类比:高速公路
最佳并发点 = 车流量大但不堵车的状态。每辆车都能以接近限速行驶,道路利用率最高。 最大并发点 = 塞车了但还在蠕动。虽然没有完全停下来,但车速已经很慢了。 超过最大并发点 = 完全堵死。连蠕动都做不到了。
示例
实际压测数据示例:
| 并发数 | QPS | P95 RT | 错误率 | 判断 |
|---|---|---|---|---|
| 50 | 200 | 100ms | 0% | 线性增长阶段 |
| 100 | 400 | 110ms | 0% | 线性增长阶段 |
| 200 | 720 | 150ms | 0% | 增速放缓 |
| 300 | 850 | 250ms | 0.1% | 最佳并发点附近 |
| 400 | 880 | 500ms | 1% | 进入饱和区 |
| 500 | 860 | 1200ms | 3% | 最大并发点附近 |
| 600 | 700 | 3000ms | 10% | 过载 |
| 800 | 400 | 8000ms | 25% | 严重过载 |
| **结论:**最佳并发 ≈ 300,最大并发 ≈ 500。日常负载应控制在 300 以下,峰值不应超过 500。 |
课堂练习
**练习 5:**根据以下压测数据,判断最佳并发点和最大并发点:
| 并发 | QPS | P95 RT | 错误率 |
|---|---|---|---|
| 10 | 95 | 50ms | 0% |
| 50 | 450 | 60ms | 0% |
| 100 | 850 | 80ms | 0% |
| 200 | 1500 | 120ms | 0.05% |
| 300 | 1800 | 200ms | 0.2% |
| 400 | 1850 | 400ms | 1.5% |
| 500 | 1700 | 900ms | 5% |
| 600 | 1200 | 2500ms | 15% |
- 最佳并发点在哪里?为什么?
- 最大并发点在哪里?为什么?
- 如果业务预期日常并发为 250,峰值可能到 400,系统能否满足要求?
6. Little's Law(利特尔法则)
6.1 公式
📐 Little's Law
L = λ × W
- L(系统中的请求数)= 并发数
- λ(到达速率)= 吞吐量(TPS / QPS)
- W(平均逗留时间)= 平均响应时间(秒) 即:并发用户数 = 吞吐量(TPS) × 平均响应时间(秒)
这个法则的强大之处在于:它不依赖任何具体的系统架构或分布假设,只要系统处于稳定状态,它就成立。
6.2 三种推导方向
| 已知 | 求 | 公式 |
|---|---|---|
| TPS 和 RT | 并发数 | 并发数 = TPS × RT |
| 并发数 和 RT | TPS | TPS = 并发数 / RT |
| 并发数 和 TPS | RT | RT = 并发数 / TPS |
6.3 场景应用
示例
场景 A:算并发数 系统 TPS = 200,平均 RT = 0.3 秒 并发数 = 200 × 0.3 = 60 含义:任意时刻,系统中平均有 60 个请求在被处理。
示例
场景 B:算需要的 TPS 业务需要支撑 500 并发用户,预期 RT = 0.2 秒 TPS = 500 / 0.2 = 2500 含义:服务器每秒至少要处理 2500 个请求。
示例
场景 C:预估 RT 服务器 TPS 上限是 1000,高峰期有 300 并发用户 RT = 300 / 1000 = 0.3 秒 含义:高峰期平均响应时间约 300ms,在可接受范围。
6.4 反向推导:容量规划
Little's Law 最实用的场景是容量规划——已知业务目标,反推系统需要达到的性能:
业务目标:大促期间支撑 1000 并发用户
性能要求:P95 响应时间 < 500ms(即平均 RT ≈ 300ms = 0.3s)
反推需要的 TPS:
TPS = 并发数 / RT = 1000 / 0.3 ≈ 3333 TPS
当前系统 TPS 只有 1500 → 差距约 2 倍
→ 方案 1:优化代码把 TPS 提升到 3500
→ 方案 2:水平扩容到 3 台服务器(每台 1500 → 总共 4500 TPS)
→ 方案 3:降低 RT(加缓存把 RT 从 300ms 降到 150ms → 需要 TPS = 1000/0.15 = 6667 → 反而更难)课堂练习
**练习 6:**使用 Little's Law 解答以下 5 道计算题:
- 一个 API 的 TPS 是 500,平均 RT 是 200ms。系统中同时有多少个请求在处理?
- 需要支撑 800 并发用户,要求平均 RT 不超过 400ms。系统至少需要多少 TPS?
- 系统的 TPS 极限是 2000,当前有 600 个并发用户。预计平均 RT 是多少?
- 压测发现当前系统最大 TPS = 1000,RT = 0.5s。如果业务目标是 2000 并发,RT ≤ 0.3s,需要 TPS 达到多少?当前差距有多大?
- 一个 AI 对话接口,平均 RT = 5 秒(大模型推理慢),需要支撑 100 并发。需要多少 TPS?如果当前 TPS 只有 10,怎么办?
7. Amdahl's Law(阿姆达尔定律)
7.1 核心思想
📐 Amdahl's Law
加速比 = 1 / ( S + (1-S)/N )
- S = 必须串行执行的比例(无法被并行化的部分)
- N = 并行处理的资源数量(如 CPU 核数、服务器数量)
**核心含义:**系统的整体性能提升,受限于其中无法并行化的部分。即使你加无限多的机器,提升也有一个理论上限。
7.2 数学推导
假设一个任务总耗时 T,其中:
- S 比例的部分必须串行执行(如初始化、汇总结果)
- (1-S) 比例的部分可以并行执行(如处理请求)
用 N 台机器并行后,总耗时变为:
T_new = T × S + T × (1-S) / N
加速比 = T / T_new = 1 / ( S + (1-S)/N )
当 N → ∞ 时:
加速比 → 1 / S
即:如果串行部分占 20%(S=0.2),理论最大加速比 = 1/0.2 = 5 倍
不管你加多少机器,最多只能快 5 倍。7.3 直观理解
| 串行比例 (S) | N=2 | N=4 | N=8 | N=16 | N=∞ |
|---|---|---|---|---|---|
| 5% | 1.9x | 3.5x | 5.9x | 9.1x | 20x |
| 10% | 1.8x | 3.1x | 4.7x | 6.4x | 10x |
| 20% | 1.7x | 2.5x | 3.3x | 3.9x | 5x |
| 50% | 1.3x | 1.6x | 1.8x | 1.9x | 2x |
💡 关键洞察
当串行比例为 50% 时,加再多机器也只能快 2 倍。把 16 台服务器加到 64 台,从 1.9x 提升到接近 2x——投入产出比极低。 结论:优化串行部分(降低 S)比堆机器(增加 N)更有效。
7.4 在性能优化中的应用
Amdahl's Law 告诉我们一个优化原则:先找到串行瓶颈,优先优化它。
示例
**场景:**一个 API 的处理流程如下:
- 参数校验:5ms(串行)
- 查询数据库:80ms(可并行优化:加读副本)
- 调用外部 API:100ms(可并行优化:多线程并发调用)
- 结果汇总:5ms(串行)
- 序列化返回:10ms(串行) 总耗时 = 200ms,其中串行部分 = 20ms(10%),可并行部分 = 180ms(90%) 理论最大加速比 = 1/0.1 = 10x → 理论最快 = 200/10 = 20ms 但如果不优化数据库查询那个 80ms,光加机器效果有限。**正确做法:**先加缓存把数据库查询从 80ms 降到 5ms,再看是否需要加机器。
7.5 收益递减曲线
加速比
│
5x │ ─────────────── (理论极限: 1/S)
│ ─────────
4x │ ─────
│ ────
3x │ ──
│ ─
2x │ ─
│ ─
1x │─
└──┬──┬──┬──┬──┬──┬──┬──→ 服务器数量
1 2 4 8 16 32 64
投入翻倍,收益却越来越小 → 收益递减
S = 20% 的情况:
1台 → 2台:提升 70%(值得)
2台 → 4台:提升 47%(值得)
4台 → 8台:提升 32%(勉强值得)
8台 → 16台:提升 18%(开始犹豫)
16台 → 32台:提升 9%(不太值得了)课堂练习
练习 7:
- 一个系统有 30% 的串行部分。用 4 台服务器并行处理时,加速比是多少?理论最大加速比是多少?
- 你的系统当前用 2 台服务器,想要 3 倍加速比。串行部分最多占多少?
- 有两个优化方案:方案 A 是加 4 台服务器(总共 6 台),方案 B 是优化代码将串行比例从 25% 降到 10%(维持 2 台服务器)。假设当前 2 台服务器,串行 25%,哪个方案效果更好?请计算。
8. 排队论基础
8.1 为什么要学排队论?
你有没有遇到过这样的现象:服务器 CPU 利用率只有 70%,但用户已经感觉很慢了。再加一点压力到 85%,响应时间就像坐火箭一样飙升。 排队论可以解释这个现象,并给出精确的数学关系。
8.2 M/M/1 模型
📐 M/M/1 排队模型
最简单的排队模型:一个服务窗口(如一个服务器),请求按照泊松过程到达,服务时间服从指数分布。
- ρ(利用率)= 到达速率 / 服务速率 = λ / μ
- 平均排队时间 = 服务时间 × ρ / (1 - ρ)
- 平均系统时间(排队 + 服务)= 服务时间 / (1 - ρ)
8.3 利用率 vs 等待时间:非线性关系
关键结论:等待时间不是随利用率线性增长的,而是呈指数级增长。
| 服务器利用率 (ρ) | 平均等待时间(服务时间的倍数) | 直观感受 |
|---|---|---|
| 10% | 0.11x | 几乎不用等 |
| 30% | 0.43x | 轻微等待 |
| 50% | 1.0x | 等和处理一样久 |
| 70% | 2.33x | 等的时间是处理的 2 倍多 |
| 80% | 4.0x | 等的时间是处理的 4 倍 |
| 90% | 9.0x | 等的时间是处理的 9 倍! |
| 95% | 19.0x | 等的时间是处理的 19 倍! |
| 99% | 99.0x | 等的时间是处理的 99 倍!! |
8.4 图解:排队等待曲线
等待时间
(倍数)
│
99x │ │
│ │
│ ╱
19x │ ╱
│ ╱
9x │ ╱
│ ╱
4x │ ╱
│ ╱
2x │ ╱
1x │ ╱
│ ╱──
0x │────────╱
└──┬──┬──┬──┬──┬──┬──┬──┬──┬──→ 利用率
10% 20% 30% 40% 50% 60% 70% 80% 90% 100%
当利用率从 70% 增加到 90% 时(增加了 29%),
等待时间从 2.3x 飙升到 9x(增加了 290%!)
这就是为什么"感觉 CPU 还没满但已经很慢了"。8.5 对性能测试的重要启示
⚠️ 核心结论:不要把服务器跑到 80% 以上
- 70% 利用率:推荐的日常运行上限。排队等待可控
- 80% 利用率:警戒线。响应时间开始急剧上升
- 90%+ 利用率:危险区。一个小的流量波动就可能导致雪崩
💡 为什么 90% 利用率很危险?
因为真实流量是有波动的。平均 90% 意味着波峰可能瞬间达到 98-99%。在 99% 利用率下,排队时间是正常处理时间的 99 倍。这就是"明明平时都好好的,突然就崩了"的数学原因。
示例
真实场景举例: 某服务处理一个请求需要 10ms。在不同利用率下的用户体验:
| 利用率 | 处理时间 | 排队时间 | 总响应时间 | 用户体验 |
|---|---|---|---|---|
| 50% | 10ms | 10ms | 20ms | 极快 |
| 70% | 10ms | 23ms | 33ms | 很快 |
| 80% | 10ms | 40ms | 50ms | 可接受 |
| 90% | 10ms | 90ms | 100ms | 开始能感觉到延迟 |
| 95% | 10ms | 190ms | 200ms | 明显变慢 |
| 99% | 10ms | 990ms | 1000ms | 无法接受 |
| 从 50% 利用率到 99% 利用率,处理时间没变(始终 10ms),但总响应时间从 20ms 变成了 1000ms——增加了 50 倍! |
课堂练习
练习 8:
- 一个服务处理每个请求需要 20ms。当利用率为 75% 时,平均排队时间和总响应时间分别是多少?
- 如果 SLO 要求总响应时间不超过 100ms,那么利用率最多能到多少?(提示:总响应时间 = 服务时间 / (1-ρ))
- 结合排队论的知识,解释为什么容量规划时通常建议预留 30% 以上的资源余量。
9. 六种测试类型详解
9.1 基准测试(Baseline Test)
| 维度 | 说明 |
|---|---|
| 目的 | 在最低负载下(通常 1 个用户)记录系统的基准性能,作为后续所有测试的参照物 |
| 执行方式 | 1 个虚拟用户,按照完整业务流程执行所有关键接口,每个接口至少执行 10 次取平均 |
| 判定标准 | 记录每个接口的 RT、无错误。没有通过/不通过的判断,纯粹是"记录数据" |
| 典型输出 | 每个接口的基准 RT(如:登录 150ms、首页 80ms、下单 200ms) |
| 何时使用 | 每次版本迭代前都要跑一次,与上个版本的基准对比,判断是否有性能退化 |
9.2 负载测试(Load Test)
| 维度 | 说明 |
|---|---|
| 目的 | 验证系统在预期正常负载下能否稳定工作 |
| 执行方式 | 阶梯式加压到目标并发数(如 100→200→300→目标 500),每级持续 5-10 分钟 |
| 判定标准 | 在目标负载下:RT 满足 SLO、错误率 < 阈值、资源利用率 < 80% |
| 典型输出 | "在 500 并发下,P95 RT = 350ms,QPS = 850,错误率 0.1%,CPU 65%" |
| 何时使用 | 每次发版前必做。这是最基础、最常用的测试类型 |
9.3 压力测试(Stress Test)
| 维度 | 说明 |
|---|---|
| 目的 | 找到系统的极限(天花板在哪?崩了是什么表现?) |
| 执行方式 | 从目标负载继续加压:500→800→1000→1500→直到崩溃 |
| 判定标准 | 记录系统开始出问题的并发数(拐点)、完全崩溃的并发数(崩溃点)、崩溃后的表现 |
| 典型输出 | "系统在 800 并发时开始出现零星错误,1200 并发时错误率超过 10%,1500 并发时服务完全不可用" |
| 何时使用 | 了解系统极限、评估大促能扛多少、验证过载保护机制 |
9.4 稳定性测试(Endurance / Soak Test)
| 维度 | 说明 |
|---|---|
| 目的 | 发现长时间运行后才会暴露的问题(内存泄漏、连接池泄漏、日志撑满磁盘等) |
| 执行方式 | 在正常目标负载下,持续运行 4-24 小时(甚至更久) |
| 判定标准 | 长时间运行后 RT 不恶化、错误率不增长、内存/连接数稳定(不持续增长) |
| 典型输出 | "运行 8 小时后发现内存从 2GB 增长到 6GB 且未释放 → 存在内存泄漏" |
| 何时使用 | 重大版本上线前、使用新框架/中间件时、怀疑有资源泄漏时 |
9.5 尖峰测试(Spike Test)
| 维度 | 说明 |
|---|---|
| 目的 | 验证系统能否承受突发流量冲击,以及冲击后能否自动恢复 |
| 执行方式 | 低负载(如 50 并发)运行 → 瞬间飙升到高负载(如 1000 并发)→ 持续 2-5 分钟 → 回落到低负载 |
| 判定标准 | 高峰期间系统不崩溃(可以变慢但不能挂)、高峰过后能在 X 分钟内恢复正常 |
| 典型输出 | "流量突增到 10 倍时,RT 从 200ms 上升到 3s,错误率 5%。回落后 30 秒内恢复正常" |
| 何时使用 | 大促倒计时抢购、热点事件可能引发的流量洪峰、游戏开服 |
9.6 可扩展性测试(Scalability Test)
| 维度 | 说明 |
|---|---|
| 目的 | 验证加机器(水平扩容)能否线性提升系统性能 |
| 执行方式 | 1 台机器跑满 → 加到 2 台 → 4 台 → 8 台,看 TPS 是否线性增长 |
| 判定标准 | 2 台 TPS 是 1 台的 1.8x 以上算"基本线性"。如果只有 1.3x,说明有共享瓶颈 |
| 典型输出 | "1台 TPS=500,2台 TPS=950(线性度 95%),4台 TPS=1700(线性度 85%)→ 扩容效率尚可" |
| 何时使用 | 制定扩容方案前、评估加多少机器能达到目标 TPS |
9.7 六种类型对比总览
| 类型 | 并发级别 | 持续时间 | 核心问题 | 优先级 |
|---|---|---|---|---|
| 基准测试 | 最低(1用户) | 短 | 系统"空载"性能是多少? | 每次必做 |
| 负载测试 | 目标负载 | 中(30-60分钟) | 正常负载下能不能用? | 每次必做 |
| 压力测试 | 超过目标 | 中 | 系统极限在哪? | 重要版本做 |
| 稳定性测试 | 目标负载 | 长(4-24小时) | 长时间跑会不会出问题? | 重要版本做 |
| 尖峰测试 | 突发高峰 | 短 | 扛不扛得住突发冲击? | 有大促需求时做 |
| 可扩展性测试 | 逐步增加资源 | 中 | 加机器有没有用? | 需要扩容时做 |
课堂练习
**练习 9:**为以下 5 个业务场景选择最合适的测试类型,并说明理由:
- 新版本上线前,需要确认关键接口性能没有退化
- 电商平台即将迎来 618 大促,需要确认系统能否扛住
- 开发团队反馈"系统运行一段时间后会变慢,重启后恢复"
- 秒杀活动开始的瞬间,预计会有大量用户同时涌入
- 运维团队想知道加 2 台机器后系统能提升多少性能
10. 如何选择测试类型
10.1 决策流程
明确测试目标 → 判断项目阶段 → 评估风险等级 → 选择测试组合 → 制定执行计划
10.2 不同项目阶段的测试策略
场景 A:新系统首次上线
推荐组合:基准测试 + 负载测试 + 压力测试 + 稳定性测试
首次上线什么都不确定,需要全面摸底。先跑基准了解空载性能,再逐步加压找到系统边界,最后跑稳定性测试排除隐藏问题。这是最完整的测试方案。
场景 B:版本迭代发布
推荐组合:基准测试 + 负载测试
和上个版本的基准数据对比,确认新代码没有引入性能退化。在目标负载下跑一轮负载测试即可。如果改动涉及核心架构,加上稳定性测试。
场景 C:大促 / 营销活动前
推荐组合:负载测试 + 压力测试 + 尖峰测试 + 可扩展性测试
重点是验证系统在预期峰值下的表现,以及突发流量冲击的应对能力。如果当前容量不够,需要做可扩展性测试评估扩容方案。
场景 D:日常巡检
推荐组合:基准测试 + 轻量负载测试
定期(如每周或每月)自动化执行,监控性能基线是否有异常变化。无需大规模压测,主要目的是"早发现、早治理"。
场景 E:故障复盘后
推荐组合:针对故障场景的专项测试 + 回归负载测试
故障原因是什么就重点测什么。例如:故障原因是内存泄漏 → 修复后跑稳定性测试验证。故障原因是突发流量 → 做尖峰测试验证。修复后还需要跑一轮负载测试确认没有引入新问题。
10.3 决策速查表
| 你的问题 | 应该做 |
|---|---|
| "新系统能不能上线?" | 基准 + 负载 + 压力 + 稳定性 |
| "新版本有没有性能退化?" | 基准 + 负载 |
| "大促能不能扛住?" | 负载 + 压力 + 尖峰 |
| "系统跑久了会不会出问题?" | 稳定性测试(4-24h) |
| "突然来一波流量会不会崩?" | 尖峰测试 |
| "加机器能不能解决?" | 可扩展性测试 |
| "系统极限在哪?" | 压力测试 |
| "想定期监控性能变化" | 自动化基准测试 |
课堂练习
**练习 10:**你是一家 SaaS 公司的 QA 负责人。以下事件发生时,你会选择什么测试类型?
- 公司要参加一个行业展会,预计展会期间用户注册量会增长 20 倍
- 开发团队把后端从 Node.js 迁移到了 Go,需要验证新版本的性能
- 上周五线上发生了一次 OOM(Out of Memory)故障,开发修复了一个内存泄漏 bug
- 老板说"给客户承诺 99.9% 可用性和 P95 < 500ms",你需要验证能否达标
11. SLA / SLO / SLI
11.1 三个概念的关系
SLI(指标) 用什么来衡量 → SLO(目标) 要达到什么标准 → SLA(协议) 对外承诺 + 违约后果
| 概念 | 全称 | 含义 | 谁制定 | 给谁看 |
|---|---|---|---|---|
| SLI | Service Level Indicator | 服务水平指标——用什么数字来衡量服务质量 | 技术团队 | 内部 |
| SLO | Service Level Objective | 服务水平目标——指标要达到什么标准 | 技术 + 产品 | 内部 |
| SLA | Service Level Agreement | 服务水平协议——对外承诺,违反有赔偿 | 商务 + 技术 | 客户 |
示例
举例说明三者的关系:
- SLI:"我们用 P99 响应时间来衡量接口性能"
- SLO:"P99 响应时间要小于 1 秒"
- SLA:"如果月度可用性低于 99.9%,赔偿客户当月服务费的 10%"
11.2 如何制定合理的 SLO
💡 SLO 制定的两个极端
- **太松:**SLO 设为"P99 < 10s"——几乎不可能不达标,失去了监控意义
- **太紧:**SLO 设为"P99 < 50ms"——几乎不可能达标,团队每天都在"灭火",疲于应付
制定 SLO 的方法:
- **看历史数据:**过去 3 个月的实际 P99 是多少?在此基础上加 20-30% 余量作为 SLO
- **看用户预期:**用户能接受的最慢响应时间是多少?(如:电商搜索 < 1s,金融交易 < 200ms)
- **看竞品:**同类产品的性能水平如何?不能比竞品慢太多
- **看成本:**从 P99 < 1s 优化到 P99 < 200ms,可能需要 10 倍的机器成本。值不值得?
11.3 不同业务的 SLO 示例
| 业务类型 | SLI | SLO | 说明 |
|---|---|---|---|
| 电商商品页 | P95 响应时间 | < 500ms | 商品页打开慢直接影响转化率 |
| 电商下单 | P99 响应时间 | < 1s | 下单是核心链路,不允许有长尾 |
| 社交信息流 | P95 响应时间 | < 300ms | 刷 Feed 要求流畅,用户对卡顿极敏感 |
| 金融交易 | P99.9 响应时间 | < 100ms | 毫秒级差距可能影响交易结果 |
| AI 对话(TTFT) | P95 首 Token 延迟 | < 2s | 用户等第一个字的耐心有限 |
| AI 对话(端到端) | P99 总响应时间 | < 30s | 长回答可以慢,但不能超时 |
| 内部管理系统 | P90 响应时间 | < 2s | 内部员工容忍度较高 |
| 可用性 | 成功请求 / 总请求 | > 99.9%(3 个 9) | 每月最多 43 分钟不可用 |
11.4 可用性的"几个 9"
| 可用性 | 年不可用时间 | 月不可用时间 | 难度 |
|---|---|---|---|
| 99% (2 个 9) | 3.65 天 | 7.3 小时 | 基本要求 |
| 99.9% (3 个 9) | 8.76 小时 | 43 分钟 | 标准目标 |
| 99.95% | 4.38 小时 | 22 分钟 | 较高要求 |
| 99.99% (4 个 9) | 52 分钟 | 4.3 分钟 | 很难 |
| 99.999% (5 个 9) | 5.26 分钟 | 26 秒 | 极难(金融级) |
从 3 个 9 到 4 个 9,成本可能增加 10 倍
每多一个 9,需要的技术投入(冗余、容灾、自动化恢复等)和运维成本都会数量级增长。大多数业务 99.9% 足够,只有金融、医疗等关键系统需要 4 个 9 以上。
课堂练习
练习 11:
- 为以下系统制定合理的 SLO(包含 SLI 选择和目标值):
- 企业内部的 OA 审批系统
- 面向 C 端的短视频推荐接口
- 接入大模型的智能客服系统
- 如果你的系统当前 P99 = 800ms,老板要求你承诺 SLA "P99 < 500ms"。你会怎么办?直接答应?还是先做什么?
- 计算:如果 SLO 是 99.95% 可用性,每个月最多能宕机多少分钟?
12. 性能基线与红线
12.1 什么是性能基线(Baseline)
📖 定义
性能基线是系统在特定版本、特定配置下的性能快照。它是后续所有性能对比的参照标准,就像体检报告——你需要一份"健康时"的体检数据,才能判断以后是否"生了病"。
基线包含的内容:
- 每个关键接口的 RT(P50 / P90 / P95 / P99)
- 系统在目标负载下的 QPS / TPS
- 各项资源利用率(CPU、内存、磁盘 IO、网络)
- 错误率
- 测试时的环境配置(版本号、服务器规格、数据库大小等)
12.2 如何建立基线
确定测试场景 → 固定测试环境 → 执行基准测试 → 执行负载测试 → 记录完整数据 → 存档为基线 v1
注意事项:
- **环境一致性:**基线测试的环境(服务器规格、网络配置、数据量)必须和后续对比测试保持一致,否则对比没有意义
- **数据量一致:**数据库中有 100 条数据 vs 100 万条数据,性能差异可能很大
- **多次执行取稳定值:**至少跑 3 次取中位数,排除偶然波动
- **版本化管理:**每个版本的基线单独存档,如 baseline-v2.1.0、baseline-v2.2.0
12.3 基线的使用方式
示例
场景:版本迭代后的性能对比
| 接口 | v2.1.0 基线 | v2.2.0 测试 | 变化 | 判断 |
|---|---|---|---|---|
| GET /api/products | P95: 120ms | P95: 115ms | -4% | 正常 |
| POST /api/login | P95: 200ms | P95: 210ms | +5% | 正常 |
| POST /api/order | P95: 350ms | P95: 800ms | +129% | 异常!需排查 |
| GET /api/search | P95: 180ms | P95: 190ms | +6% | 正常 |
| **结论:**v2.2.0 的下单接口性能严重退化(RT 翻倍),需要排查原因后再决定是否上线。其他接口正常。 |
💡 性能退化的判定阈值
- RT 变化 ±10% 以内:正常波动,无需关注
- RT 变化 +10% ~ +30%:需要关注,评估是否可接受
- RT 变化 > +30%:明确退化,必须排查原因
12.4 什么是性能红线
⚠️ 定义
性能红线是不可逾越的底线——一旦超过,禁止上线或立即回滚。红线是对系统性能的最低要求,没有商量余地。
红线是硬性标准,和 SLO(软目标)的区别:
| 维度 | SLO(目标) | 红线(底线) |
|---|---|---|
| 性质 | 努力目标,允许偶尔不达标 | 硬性底线,不允许突破 |
| 不达标的后果 | 团队内部关注、优化 | 禁止上线 / 立即回滚 |
| 宽严程度 | 有一定弹性 | 零容忍 |
| 示例 | P95 < 300ms | P99 < 3s(超过就禁止上线) |
12.5 红线示例
| 指标 | 红线标准 | 触发动作 |
|---|---|---|
| 核心接口 P99 RT | < 3 秒 | 超过 → 禁止上线,修复后重新压测 |
| 错误率 | < 1% | 超过 → 禁止上线 |
| 线上错误率 | < 0.5% | 超过 → 立即回滚到上个版本 |
| CPU 利用率 | < 80%(目标负载下) | 超过 → 优化或扩容后才能上线 |
| 内存增长 | 8 小时稳定性测试中内存增长 < 10% | 超过 → 排查内存泄漏 |
| 性能退化幅度 | 核心接口 RT 变化不超过基线的 +30% | 超过 → 排查原因,确认是否可接受 |
12.6 基线与红线的关系
响应时间
│
│ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ 红线 (3000ms) ← 不可逾越
│
│
│ · · · · · · · · · · · · · · · · · · · SLO 目标 (500ms) ← 努力方向
│
│ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ 当前基线 (300ms) ← 实际水平
│
└──────────────────────────────────────→
基线 = "我现在在哪"
SLO = "我想去哪"
红线 = "不能掉到这以下"✅ 最佳实践
- 每个版本发布前跑一次基准测试,更新基线
- 将基线数据和红线标准写入 CI/CD 流水线,自动化判定
- 性能红线写入团队的发布 Checklist,作为上线的必要条件
- 定期(如每季度)回顾和调整红线标准,随着系统演进而更新
课堂练习
练习 12:
- 你负责一个在线教育平台。请为以下接口制定性能基线和红线:
- 课程列表页 GET /api/courses
- 视频播放 GET /api/video/stream
- 提交作业 POST /api/homework
- AI 智能批改 POST /api/ai-grade
- 以下压测结果是否触发红线?
- 接口 A:P99 = 2800ms(红线 3000ms)
- 接口 B:错误率 = 1.2%(红线 1%)
- 接口 C:RT 比基线增长了 25%(红线 30%)
- 为什么"红线"要比"SLO"更宽松?如果红线比 SLO 还严格会怎样?
补充参考答案要点
- 基础篇练习的核心答案应能正确区分吞吐、响应时间、并发、资源利用率和稳定性这几个基本概念。
- 涉及计算题时,至少要会手算平均值、P95、最佳并发点和 Little's Law 的基本应用。
- 测试类型选择题的关键不是死记,而是能根据场景解释为什么选压测、负载、稳定性或容量测试。