全链路压测体系:压测目标设定与容量评估,压测数据隔离,压测流量模型设计
聊到全链路压测,很多团队上来就开干。我见过不少项目,压测工具配好了,脚本写完了,结果压出来的数据根本没法用。为什么?因为目标没定清楚,数据没隔离好,流量模型也跟真实场景对不上。
说白了,全链路压测不是跑个脚本就完事。它是一套系统工程。今天我就把这块掰开揉碎了讲,重点说三件事:目标怎么定、容量怎么算、数据怎么隔离、流量模型怎么设计。
一、压测目标设定:别拍脑袋,要算清楚
我习惯把压测目标分成三层:业务目标 → 技术指标 → 压测场景。你想想看,如果老板说“双十一要扛住”,那具体扛多少?是100万QPS还是500万?
1.1 业务目标拆解
举个例子。某电商平台大促,业务目标是“1小时内完成1000万笔订单”。那技术指标怎么算?
- 平均每秒订单数:1000万 ÷ 3600秒 ≈ 2778 笔/秒
- 峰值系数:一般取2~3倍,按3倍算 ≈ 8334 笔/秒
- 每个订单涉及3次接口调用(下单、支付、回调)→ 峰值QPS ≈ 25000
核心公式:
目标QPS = (业务总量 ÷ 时间窗口) × 峰值系数 × 接口调用次数
1.2 技术指标设定
我个人习惯用“三个九”原则:
| 指标 | 目标值 | 说明 |
|---|---|---|
| 成功率 | ≥ 99.9% | 压测期间请求成功率 |
| P99延迟 | ≤ 500ms | 99%的请求在500ms内完成 |
| 错误率 | ≤ 0.1% | 超时、5xx等错误 |
注意: 我曾经在项目中遇到过,目标定得太高,结果压测环境根本跑不到那个量级。后来发现是压测机本身成了瓶颈。所以目标设定时,也要考虑压测基础设施的承载能力。
二、容量评估:从单机到集群的推演
容量评估不是玄学。我一般分三步走:单机摸底 → 线性扩展验证 → 集群容量推算。
2.1 单机摸底
先压单台机器,找到它的极限。比如一台4C8G的实例,压测发现:
- CPU到80%时,QPS约5000
- 再往上压,延迟开始飙升
- CPU到95%时,QPS反而下降到4000(因为上下文切换开销)
所以这台机器的安全水位是:5000 × 0.7 = 3500 QPS。留30%的余量应对突发。
2.2 线性扩展验证
单机3500,那10台是不是35000?不一定。我见过最坑的情况是,加到8台时性能反而下降了。为什么?因为共享资源(数据库、缓存、消息队列)成了瓶颈。
我的经验: 每次加机器后,都要重新压一次。如果扩展效率低于80%,说明架构有问题。比如数据库连接池没调大,或者缓存分片不均匀。
2.3 集群容量推算
假设单机安全水位3500 QPS,扩展效率85%,目标QPS是25000:
所需机器数 = 25000 ÷ (3500 × 0.85) ≈ 8.4 → 取9台
嗯,这里要注意。这个公式只适用于无状态服务。有状态服务(比如Session粘滞)要单独评估。
三、压测数据隔离:影子库 vs 影子表
数据隔离是压测里最容易出问题的地方。我见过有人直接在线上库压测,结果把用户数据搞乱了。那叫一个惨。
3.1 影子库方案
简单说,就是给压测流量单独建一个数据库。比如线上库叫db_online,影子库叫db_shadow。
- 优点: 完全隔离,互不影响
- 缺点: 成本高,需要额外维护一套库
我建议在压测规模大、数据量大的场景用影子库。比如双十一压测,数据量几十TB,影子表根本放不下。
3.2 影子表方案
在同一个库里,建一套带后缀的表。比如orders表,影子表叫orders_shadow。
-- 线上表
CREATE TABLE orders (
id BIGINT PRIMARY KEY,
user_id BIGINT,
amount DECIMAL(10,2),
create_time DATETIME
);
-- 影子表
CREATE TABLE orders_shadow LIKE orders;
压测时,通过中间件或ORM拦截,把SQL路由到影子表。我习惯在请求头里加一个x-shadow: true的标记,网关层根据这个标记做路由。
关键点: 影子表要跟线上表结构完全一致。包括索引、分区、存储引擎。不然压测结果不准。
3.3 数据清理策略
压测结束后,影子数据必须清干净。我曾经遇到过,压测数据没清完,结果第二天线上报表里多出了几百万条测试订单。
我的做法是:
- 压测前记录影子表的基线数据量
- 压测后对比增量,按批次删除
- 用定时任务兜底,24小时后自动清理
四、压测流量模型设计:模拟真实用户行为
流量模型设计不好,压测结果就是自欺欺人。你想想看,如果所有请求都是均匀的,那跟真实场景差太远了。
4.1 流量特征分析
我一般从三个维度分析:
- 时间分布: 白天高、晚上低?还是凌晨有波峰?
- 接口比例: 登录、浏览、下单、支付,各占多少?
- 参数分布: 热门商品被频繁访问,冷门商品几乎没人看
4.2 流量模型实现
以JMeter为例,我会这样设计:
// 1. 登录接口:占10%的流量
// 2. 浏览商品:占40%的流量
// 3. 加购物车:占20%的流量
// 4. 下单:占20%的流量
// 5. 支付:占10%的流量
// 使用随机控制器,按比例分配
// 参数用CSV文件,模拟不同用户、不同商品
嗯,这里要注意。真实场景中,用户不是同时操作的。所以要用思考时间来模拟用户停顿。我一般设成100~500ms的随机延迟。
4.3 流量模型验证
压测跑起来后,我会对比线上真实流量和压测流量的分布。如果发现某个接口的比例偏差超过10%,就要调整模型。
一个小技巧: 用Kibana或Grafana,把线上流量和压测流量画在同一张图上。一眼就能看出模型准不准。
五、总结
全链路压测,说白了就是三个字:真、准、稳。
- 真: 流量模型要真实,别用均匀分布糊弄自己
- 准: 容量评估要算清楚,留足余量
- 稳: 数据隔离要做好,别把线上搞崩了
我做了这么多年SRE,最深的体会是:压测不是为了证明系统没问题,而是为了提前发现问题。所以别怕压出问题,怕的是压不出来问题。
好了,这一章就聊到这儿。下一章我们讲压测工具选型和脚本编写,到时候我会分享一些我踩过的坑。