微服务全链路压测与容量规划
大促前不压测,等于裸奔。全链路压测用真实流量模型打满整个链路,找出瓶颈与容量上限;容量规划则回答"到底要备多少机器"。本文覆盖压测工具选型、链路隔离与标记、TPS/QPS 模型、瓶颈定位与扩容策略。
压测基础
单机压测 vs 全链路压测
单机/单服务压测:
├─ 只压一个服务(或接口)
├─ 用于服务自身性能验证
└─ 局限性:无法发现跨服务瓶颈
全链路压测:
├─ 按真实调用链压测(网关→订单→库存→支付)
├─ 覆盖中间件(DB、Redis、MQ)
├─ 发现全链路瓶颈与容量
└─ 大促前的标准动作压测名词
| 名词 | 含义 |
|---|---|
| QPS | 每秒请求数(入口层) |
| TPS | 每秒事务数(业务完成量) |
| 并发数 | 同时处理的请求数 |
| 响应时间 | RT(平均/P95/P99) |
| 吞吐量 | 系统单位时间处理能力 |
| 拐点 | 性能开始劣化的临界点 |
核心关系(Little 定律):
并发数 = QPS × 平均响应时间
├─ QPS = 1000,RT = 0.1s → 并发 = 100
└─ 并发是结果不是目标,QPS 与 RT 才是一、压测工具选型
常用工具对比
| 工具 | 特点 | 适用场景 |
|---|---|---|
| JMeter | 老牌、图形化、插件丰富 | 接口级压测、脚本化 |
| Gatling | Scala DSL、高并发、报表好 | 测试人员做链路压测 |
| Locust | Python 脚本、分布式 | 开发自测、快速压测 |
| wrk / ab | 轻量、命令行 | 单机快速压测 |
| 云压测平台 | 超大流量、流量编排 | 大促全链路压测 |
压测流量生成
全链路压测流量来源:
├─ 线上流量复制(真实流量回放)
│ └─ 最真实,但要处理脏数据
├─ 压测脚本构造(JMeter/Gatling 模拟)
│ └─ 可控性高,场景可编排
└─ 混合:核心链路用复制流量,边缘用脚本二、链路隔离与标记
压测流量污染问题
压测流量污染:
├─ 压测订单进入真实订单表 → 污染统计
├─ 压测请求触发真实短信/支付 → 事故
└─ 需要把压测流量与线上流量隔离压测标记
压测标记机制:
├─ 请求头标记:压测流量带特殊 Header(x-mt: true)
├─ 透传:Gateway 识别后透传到下游
├─ 影子表:压测数据写入影子库/影子表
└─ 中间件隔离:压测流量走独立 MQ topic / Redis key
实现:
├─ 网关识别压测 Header → 加标记透传
├─ 数据源路由:按标记路由到影子库
└─ 下游服务透传标记(Feign/HTTP 拦截器)影子库方案
影子表/影子库:
├─ 业务表创建影子版本(order_shadow)
├─ MyBatis/数据源插件按标记路由
└─ 压测后清理影子数据
隔离清单:
├─ 数据库:影子表
├─ Redis:独立 key 前缀 / 独立实例
├─ MQ:独立 topic
└─ 外部调用:Mock 或降级(不发真实短信)三、TPS/QPS 模型
压测模型设计
设计压测模型的步骤:
1. 统计线上流量构成(接口比例、链路比例)
2. 确定压测目标(大促峰值 = 日常 × 倍数)
3. 构造流量模型(按比例混合请求)
4. 分场景压测(单链路 → 全链路)
大促目标估算:
├─ 日常峰值 QPS = 5000
├─ 大促预估 = 日常 × 5 = 25000
└─ 压测目标:全链路稳定支撑 25000 QPS压测阶段
压测节奏:
1. 基准压测:单服务,确定单机能力
2. 链路压测:核心链路,找跨服务瓶颈
3. 全链路压测:模拟大促峰值流量
4. 持续压测:长时间运行,找内存泄漏/稳定性问题
每次压测记录:
├─ 压测配置(并发、时长、模型)
├─ 关键指标(QPS、RT、错误率)
└─ 系统指标(CPU、内存、GC、连接数)四、瓶颈定位
常见瓶颈点
全链路瓶颈排查顺序:
├─ 1. 入口:Gateway/Web 服务器线程池
├─ 2. 业务:各服务线程池、CPU
├─ 3. 数据库:慢 SQL、连接数、锁等待
├─ 4. 缓存:Redis 命中率、热点
├─ 5. 消息:MQ 积压、消费速度
└─ 6. 外部:第三方接口超时
典型表现:
├─ QPS 上不去、RT 陡增 → 有瓶颈卡住
├─ 某服务 CPU 100% → 计算密集或死循环
├─ DB 连接池满 → SQL 慢/锁
└─ 线程池排队 → 下游慢压测中的观测
压测时观测手段:
├─ 指标:Prometheus 实时看 QPS/RT/错误率
├─ 链路:SkyWalking/Jaeger 看各节点耗时
├─ JVM:Arthas、GC 日志
├─ 数据库:慢 SQL 日志、连接池监控
└─ 排队:各服务线程池积压
定位方法:
├─ 链路追踪找"最耗时节点"
├─ 逐层摘除:从网关往下逐层压,定位容量上限
└─ 对比实验:关掉缓存/切影子库看差异五、扩容缩容策略
扩容方式
扩容手段:
├─ 水平扩容(加实例):
│ ├─ K8s HPA 自动扩缩
│ ├─ Nacos 自动注册新实例
│ └─ 无状态服务可无限扩
├─ 垂直扩容(加配置):
│ └─ 升级实例规格(CPU/内存)
├─ 缓存扩容:Redis 集群扩容
├─ 数据库扩容:读写分离、分库分表
└─ 消息扩容:增加分区、消费实例容量评估公式
单服务容量计算:
单实例 QPS × 实例数 = 总容量
需求 QPS ÷ 单实例 QPS × 冗余系数 = 实例数
实例数估算:
├─ 目标:25000 QPS
├─ 单实例:2000 QPS(压测得出)
├─ 冗余 30%:25000 ÷ 2000 × 1.3 ≈ 17 实例
└─ 结论:至少 17 个实例(含故障容错再补)
数据库容量:
├─ QPS × RT 计算连接需求
├─ 连接池上限 = 实例数 × 每实例连接数
└─ 超出 → 读写分离/分库分表缩容策略
缩容原则:
├─ 大促结束后逐步缩容(避免流量回落引发抖动)
├─ 缩容要保留缓冲(不能恰好等于需求)
├─ HPA 自动缩容有冷却期
└─ 记录容量数据,为下次规划提供依据六、容量规划
规划方法
容量规划三步:
1. 摸清现状:压测得出各环节容量上限
2. 预测未来:业务增长、大促峰值预估
3. 匹配资源:按峰值 + 冗余预留容量
规划维度:
├─ 应用实例数
├─ 数据库连接与磁盘
├─ Redis 内存与带宽
├─ MQ 吞吐与存储
└─ 带宽与网关容量压测报告
压测报告应包含:
├─ 压测环境与配置
├─ 峰值结果(QPS/RT/错误率)
├─ 瓶颈清单(按严重度)
├─ 优化建议(SQL、缓存、扩容)
└─ 容量结论(各环节上限与建议配置)
产出:
├─ 容量模型(实例数/DB 连接/缓存规格)
├─ 扩容预案(大促扩多少、何时扩)
└─ 风险清单(已知瓶颈与规避)七、大促压测实战流程
大促压测标准流程:
1. 目标确定:峰值 QPS、RT 目标
2. 环境准备:影子库、压测标记、独立集群
3. 数据准备:构造压测数据(账号、商品)
4. 场景设计:核心链路 + 混合流量模型
5. 压测执行:分级加压、观测指标
6. 瓶颈定位与优化:逐层排查、优化复测
7. 容量确认:实例数、连接数、缓存规格
8. 扩容预案:预扩数量、触发条件、操作步骤
9. 复盘沉淀:压测报告、容量模型、经验教训总结
全链路压测与容量规划的核心是**"用数据说话"**:压测探明每个环节的真实容量上限,容量规划按"峰值 + 冗余"预留资源。压测的关键在链路隔离(影子库/标记透传)与模型设计(按线上比例构造流量),定位瓶颈靠链路追踪与逐层压测,扩缩容要结合 HPA 与容量数据动态调整。一次高质量的全链路压测,产出的不只是"通过",更是可执行的扩容预案与风险清单。