第4章:容量规划与压测

容量规划这事儿,说白了就是回答一个问题:你的系统到底能扛多少流量?

我见过太多团队,平时不关注容量,一到双十一就手忙脚乱。要么机器加多了浪费钱,要么加少了直接挂掉。其实,容量规划不是拍脑袋,它有一套成熟的方法论。

4.1 容量评估方法

容量评估,我习惯从三个维度入手:业务指标、资源指标、性能指标。

  • 业务指标:比如QPS、TPS、DAU、订单量。这些决定了你的系统要处理多少请求。
  • 资源指标:CPU、内存、磁盘IO、网络带宽。这些决定了你的机器能不能扛住。
  • 性能指标:响应时间、错误率、吞吐量。这些决定了用户体验好不好。

举个例子。假设你的业务目标是支撑100万DAU,每个用户平均发起10次请求。那你的系统峰值QPS大概是多少?

# 粗略估算
DAU = 1,000,000
人均请求数 = 10
总请求数 = 10,000,000
峰值系数(通常取0.15~0.2)= 0.15
峰值QPS = 10,000,000 * 0.15 / (24 * 3600) ≈ 17.4 QPS

嗯,这只是个粗略值。实际中,我还会考虑流量毛刺。比如秒杀活动,瞬间流量可能是平时的几十倍。这时候,你得预留足够的buffer。

核心公式:
所需容量 = 预估峰值流量 × 安全系数(通常1.5~3倍)

4.2 全链路压测

容量评估是纸上谈兵,全链路压测才是真刀真枪的实战。

我在项目中遇到过一个问题:单机压测表现很好,但一上全链路,系统就崩了。为什么?因为单机压测忽略了依赖服务和网络瓶颈。

全链路压测的核心要点:

  1. 流量模拟要真实:不能只压一个接口,要模拟用户真实行为。比如登录、浏览、下单、支付,一个流程走下来。
  2. 数据隔离:压测数据不能污染线上数据。我习惯用影子表或压测标记来区分。
  3. 监控全覆盖:压测期间,所有服务的CPU、内存、IO、网络、GC都要盯着。任何一个环节出问题,都可能成为瓶颈。

小技巧:全链路压测最好在低峰期进行。比如凌晨2点到6点。我曾经有一次白天压测,直接把线上数据库打挂了,教训深刻。

4.3 流量回放

流量回放,是压测的另一种形式。它把线上真实的请求录下来,然后在新系统或新版本上重放。

这样做的好处很明显:真实、无死角。你压测可能漏掉某些边界情况,但流量回放不会。

流量回放的常见工具:

  • GoReplay:轻量级,支持HTTP流量录制和回放。
  • TCPCopy:可以复制TCP流量,适合更底层的测试。
  • JVM-Sandbox:适合Java应用,可以录制方法级别的调用。

我个人习惯用GoReplay。它的配置很简单:

# 录制流量
gor --input-raw :80 --output-file requests.gor

# 回放流量
gor --input-file requests.gor --output-http "http://new-server:8080"

注意,流量回放时,要确保幂等性。比如下单接口,回放一次就真的下单了。我一般会配合mock服务或测试环境来避免数据污染。

避坑指南:我曾经在回放流量时,忘记过滤掉写操作,结果测试环境里多了几万条订单。从那以后,我每次回放前都会检查:只读接口可以回放,写接口必须mock。

4.4 容量水位线设置

容量水位线,就是告诉你什么时候该扩容,什么时候该缩容。

我习惯设置三个水位线:

水位线 含义 触发动作
安全水位 资源使用率 < 60% 正常运营,无需操作
预警水位 资源使用率 60%~80% 检查扩容计划,准备资源
危险水位 资源使用率 > 80% 立即扩容,或限流降级

为什么是80%?因为当资源使用率超过80%时,系统很容易出现雪崩效应。比如CPU到了90%,响应时间变长,请求堆积,然后CPU更高,恶性循环。

你想想看,如果等到CPU到95%才扩容,可能已经来不及了。所以,我建议把预警水位设在70%,给自己留出反应时间。

4.5 弹性伸缩策略

弹性伸缩,就是让系统根据负载自动扩缩容。说白了,就是机器自己会动。

弹性伸缩有两种模式:

  • 水平伸缩:加机器或减机器。适合无状态服务,比如Web服务器。
  • 垂直伸缩:升级或降级机器配置。适合有状态服务,比如数据库。

我主要讲水平伸缩。它的核心是伸缩策略:

  1. 基于指标:比如CPU超过70%就加一台机器,低于30%就减一台。这是最常用的方式。
  2. 基于时间:比如每天10点到12点是高峰期,提前扩容。适合有规律的业务。
  3. 基于预测:用机器学习预测未来流量,提前扩容。这个比较高级,我还没在生产环境大规模用过。

举个例子,Kubernetes的HPA(Horizontal Pod Autoscaler)配置:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: my-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70

这个配置的意思是:当CPU平均使用率超过70%时,自动增加Pod数量,最多10个;低于70%时,自动减少,最少3个。

注意:弹性伸缩不是万能的。对于有状态服务(比如数据库),伸缩起来很麻烦。我建议无状态服务用水平伸缩,有状态服务用垂直伸缩+读写分离。

最后,我想说一句:容量规划不是一次性的工作。业务在变,流量在变,你的容量规划也得跟着变。我每季度都会做一次容量复盘,看看之前的规划准不准,然后调整下一季度的策略。

嗯,这就是我对容量规划与压测的理解。希望能帮到你。

总结一下:容量评估是基础,全链路压测是验证,流量回放是补充,水位线是预警,弹性伸缩是自动响应。五者缺一不可。

容量规划与压测知识体系 容量规划与压测 容量评估方法 全链路压测 流量回放 容量水位线设置 弹性伸缩策略 业务指标/资源指标/性能指标 流量模拟/数据隔离/监控全覆盖 GoReplay/TCPCopy/幂等性 安全/预警/危险三级水位 基于指标/时间/预测

想要更多资料,联系可可