3、容量规划与压测:容量评估方法论、全链路压测设计、压测数据隔离、压测指标分析、容量水位线设定

容量规划与压测,说白了就是回答三个问题:系统能扛多少?瓶颈在哪?什么时候该扩容?

我见过太多团队,平时不压测,上线前突击跑一轮,结果压出几个慢SQL就草草收场。真正上线后,流量一来直接雪崩。嗯,这章咱们就把这块讲透。

3.1 容量评估方法论

容量评估不是拍脑袋。我个人习惯用「三段式评估法」:

  1. 业务预估:根据历史峰值、活动计划、用户增长曲线,算出未来一段时间的流量预期。
  2. 资源映射:把业务流量映射到CPU、内存、IO、网络等资源消耗上。
  3. 冗余设计:在评估结果上乘以1.5~2的冗余系数,应对突发流量。

核心公式

单机容量 = 单机QPS / 单请求资源消耗

所需机器数 = 预估峰值QPS / (单机容量 × 冗余系数)

举个例子。我曾经负责过一个秒杀系统,业务方说峰值QPS大概10万。我按单机2000 QPS算,冗余系数取1.5,算出来需要75台机器。结果上线当天实际峰值到了12万,还好冗余留够了,没出事。

我的经验:冗余系数不要死板。核心链路取2.0,非核心链路取1.3。为什么?核心链路挂了就是事故,非核心链路降级就行。

3.2 全链路压测设计

全链路压测,不是单机压测的简单叠加。它要模拟真实用户请求的完整路径:从网关、应用、缓存、数据库,到下游依赖。

我建议按以下步骤设计:

  1. 压测场景定义:确定压测的接口、流量模型(匀速/脉冲/阶梯)、数据量级。
  2. 压测数据准备:构造与生产环境分布一致的数据,包括用户ID、商品ID、订单状态等。
  3. 压测链路染色:通过请求头或参数标记压测流量,方便后续隔离和监控。
  4. 压测执行:从低到高逐步加压,观察系统表现。
  5. 压测停止条件:设定熔断阈值,比如CPU超过80%或错误率超过1%时自动停止。

避坑指南:我曾经在一次压测中,忘了给压测流量打标,结果压测数据混入了生产库的统计报表。排查了整整两天。从那以后,我强制要求所有压测请求必须携带"x-pt-test: true"头,并在网关层做拦截。

3.3 压测数据隔离

数据隔离是压测中最容易出问题的地方。我总结了三层隔离策略:

隔离层级 实现方式 适用场景
逻辑隔离 在业务表中增加压测标记字段 数据量小、表结构简单的场景
物理隔离 使用独立的压测数据库或缓存集群 核心交易链路、数据敏感场景
影子库表 在同一个实例中创建影子表(如order_pt) 需要与生产环境保持相同索引和存储引擎的场景

我个人最推荐影子库表方案。为什么?因为它既保留了生产环境的物理特性(索引、分区、存储引擎),又不会污染真实数据。实现起来也不复杂:

// 压测流量拦截器示例
public class PtDataIsolationInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String ptFlag = request.getHeader("x-pt-test");
        if ("true".equals(ptFlag)) {
            // 设置压测上下文
            PtContext.setIsPt(true);
            // 动态切换数据源到影子库
            DataSourceHolder.setDataSource("shadow");
        }
        return true;
    }
}

注意:影子库的DDL变更必须与生产库同步。我见过有人改了生产表结构,忘了改影子表,结果压测时一直报错。嗯,这种低级错误,自动化脚本就能避免。

3.4 压测指标分析

压测跑完了,一堆数据摆在那,怎么看?我习惯从三个维度分析:

  • 吞吐量:QPS、TPS、吞吐量曲线是否平滑。如果曲线剧烈抖动,说明系统不稳定。
  • 响应时间:平均RT、P99、P999。重点关注P99,它代表了绝大多数用户的体验。
  • 资源利用率:CPU、内存、IO、网络。哪个先到瓶颈,哪个就是短板。

举个例子。有一次压测,QPS到了5000时,P99突然从50ms飙升到500ms。我一看CPU才60%,内存也正常。后来发现是数据库连接池满了。嗯,这就是典型的「连接池瓶颈」——资源没打满,但连接数不够了。

我的分析套路

  • 先看错误率,超过0.1%就要停。
  • 再看P99,超过500ms就要排查。
  • 最后看资源,哪个先到80%就优化哪个。

3.5 容量水位线设定

容量水位线,就是告诉你「什么时候该扩容」的阈值。我把它分为三级:

水位级别 触发条件 应对措施
安全水位 CPU < 60%,P99 < 200ms 正常运营,无需操作
警戒水位 CPU 60%~80%,P99 200~500ms 准备扩容预案,通知运维
危险水位 CPU > 80%,P99 > 500ms 立即扩容或降级

水位线不是拍出来的。我通常的做法是:先压测找到系统的极限QPS,然后取极限值的70%作为警戒水位,80%作为危险水位。为什么留20%的余量?因为压测是理想环境,线上流量更复杂。

避坑指南:我曾经设定过「CPU超过90%自动扩容」的规则。结果有一次压测时,CPU瞬间冲到95%,自动扩容触发了,但新机器启动需要3分钟。这3分钟里系统已经挂了。后来我改成「CPU超过80%持续30秒」才触发扩容,给了系统缓冲时间。

3.6 知识体系总览

下面这张图,把容量规划与压测的核心逻辑串起来了。你想想看,从评估到压测,再到隔离、分析、设水位线,每一步都环环相扣。

容量规划与压测知识体系 容量评估方法论 业务预估 → 资源映射 → 冗余设计 全链路压测设计 场景定义 → 数据准备 → 链路染色 压测数据隔离 逻辑隔离 / 物理隔离 / 影子库表 压测指标分析 吞吐量 → 响应时间(P99/P999) → 资源利用率 容量水位线设定 安全水位(CPU<60%) → 警戒水位(60-80%) → 危险水位(>80%) 反馈闭环:压测结果反哺容量评估,持续优化 核心原则:留有余量

这张图你看懂了吗?从上到下,先评估容量,再设计压测,然后隔离数据,分析指标,最后设定水位线。底部的反馈闭环说明,压测结果要反哺到容量评估中,形成持续优化的循环。

最后说一句:容量规划不是一次性工作。每次大促、每次架构升级,都要重新压测、重新设水位线。我见过最惨的案例,就是去年压测的数据今年还在用,结果线上直接被打爆。嗯,别偷懒,该压就压。


专注资料整理