容量规划与压测
问题
大促活动或新功能上线前,如何评估系统容量、制定压测方案、做好弹性扩缩容?
答案
容量规划流程
第一步:QPS 评估
从业务量推导技术指标
日均 UV = 500 万
日均 PV = 5000 万
高峰流量倍数 = 5 倍
平均 QPS = 5000万 / 86400 ≈ 580
峰值 QPS = 580 × 5 = 2900
大促峰值 = 2900 × 3 = 8700(预留 3 倍余量)
关键接口的读写比:
| 接口 | 占比 | QPS |
|---|---|---|
| 商品详情(读) | 60% | 5220 |
| 搜索(读) | 20% | 1740 |
| 下单(写) | 5% | 435 |
| 支付(写) | 3% | 261 |
第二步:单机容量压测
使用 JMeter / wrk 压测单机
# wrk 压测
wrk -t12 -c400 -d30s --latency http://service:8080/api/orders
# 输出
# Requests/sec: 1200 ← 单机 QPS
# Latency Avg: 45ms ← 平均 RT
# Latency P99: 200ms ← P99 RT
单机容量参考(8C16G):
| 接口类型 | QPS | RT (P99) |
|---|---|---|
| 纯缓存读 | 3000-5000 | < 10ms |
| DB 读 | 800-1500 | < 50ms |
| DB 写 | 300-800 | < 100ms |
| 复杂业务 | 200-500 | < 200ms |
第三步:集群规模计算
机器数量计算
目标峰值 QPS = 8700
单机容量 = 1200 QPS
安全水位 = 70%(不打满,预留 buffer)
需要机器数 = 8700 / (1200 × 0.7) ≈ 11 台
加上冗余:11 × 1.5 ≈ 17 台(保证挂两台不影响)
全链路压测
全链路压测要点:
- 影子库/影子表:压测数据不污染生产数据
- 流量染色:压测请求带标记,中间件识别并路由到影子资源
- 逐步加压:10% → 30% → 50% → 80% → 100%
- 关注指标:QPS、RT、错误率、CPU、内存、GC
弹性扩缩容
K8s HPA 自动扩缩
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: order-service-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: order-service
minReplicas: 5
maxReplicas: 50
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60 # CPU 超 60% 扩容
水位线监控
| 指标 | 绿色 | 黄色 | 红色 |
|---|---|---|---|
| CPU | < 60% | 60-80% | > 80% |
| 内存 | < 70% | 70-85% | > 85% |
| 连接池 | < 60% | 60-80% | > 80% |
| MQ 积压 | < 1000 | 1000-10000 | > 10000 |
常见面试问题
Q1: 你们压测是怎么做的?
答案:
- 梳理核心链路和关键接口
- 单机压测确定单机容量
- 全链路压测验证集群容量
- 使用影子库隔离压测数据
- 逐步加压观察各组件水位
- 找到瓶颈点优化后再压
Q2: 如何做到不影响生产数据?
答案:
- 流量染色:压测请求 Header 加标记
- 影子库:压测 SQL 路由到单独的影子库
- 影子 MQ:压测消息发到影子 Topic
- 影子缓存:Key 加前缀
shadow:
Q3: 常见的性能瓶颈在哪里?
答案:
按发现概率排序:
- 数据库:慢 SQL、连接池打满
- 缓存:热 Key、大 Key、穿透
- 下游服务:超时传递、雪崩
- GC:频繁 Full GC
- 网络:带宽打满、DNS 解析慢