4. 伸缩策略(上):基于CPU/内存利用率的动态伸缩策略配置

动态伸缩这事儿,说白了就是让云平台自己判断“该加机器了”或者“该减机器了”。

我个人习惯把这种策略叫做“自动挡”。你设定好规则,剩下的交给云平台。但很多同学上来就踩坑——规则设得太敏感,结果半夜三点给你弹出来20台机器,第二天一看账单直接傻眼。

4.1 核心指标:CPU和内存,到底看哪个?

CPU利用率和内存利用率,是最常用的两个指标。但你不能无脑选。

指标 适用场景 典型阈值 注意事项
CPU利用率 计算密集型应用(如视频转码、科学计算) 扩容:70%~80%
缩容:20%~30%
注意CPU Burst场景,短时尖峰可能误触发
内存利用率 内存密集型应用(如缓存、大数据处理) 扩容:75%~85%
缩容:30%~40%
内存泄漏会导致持续扩容,需配合健康检查
两者组合 通用型应用(如Web服务、API网关) 任一指标超过阈值即扩容 避免“与”逻辑,否则扩容响应太慢
我的经验: 对于大多数Web应用,我建议优先看CPU。内存利用率往往有滞后性——等你看到内存飙高时,其实GC已经频繁触发,应用性能早就下降了。

4.2 冷却时间:别让系统“抽风”

冷却时间(Cooldown Period)是动态伸缩里最容易忽略的参数。

举个例子:你的扩容阈值设的是CPU > 75%。某次流量突增,CPU冲到80%,触发扩容。新机器启动需要2分钟。在这2分钟里,CPU可能因为负载分摊降到了60%。但如果没有冷却时间,系统会立刻判定“CPU低于75%了,缩容吧”——结果刚缩完,流量又来了,CPU再次飙升,又扩容……

这就叫“震荡”。

我曾经踩过的坑: 给一个电商平台配伸缩策略,冷却时间设了30秒。结果双十一大促时,系统在10分钟内反复扩缩了15次,产生了大量“僵尸实例”的启动和销毁费用。后来我把冷却时间改到120秒,问题才解决。

一般建议:

  • 扩容冷却时间: 60~180秒(取决于实例启动速度)
  • 缩容冷却时间: 120~300秒(缩容要更保守)

4.3 阈值设置:别太死板

阈值不是拍脑袋定的。我见过有人直接设“CPU > 50%就扩容”,结果集群规模翻了一倍,利用率反而更低——因为每台机器都在空转。

正确的做法是:

  1. 先压测: 用工具(如wrk、ab、JMeter)模拟真实流量,找到应用的性能拐点。
  2. 留余量: 阈值不要设到极限。比如压测发现CPU到85%时响应时间开始恶化,那扩容阈值就设在70%。
  3. 分时段: 白天和晚上的阈值可以不同。白天流量大,阈值可以设低一点;晚上流量小,阈值可以设高一点。
核心原则: 扩容要快,缩容要慢。宁可多跑几台机器,也别让用户感受到延迟。

4.4 配置示例:AWS Auto Scaling + 阿里云ESS

不同云厂商的配置大同小异。我拿两个主流平台举例。

4.4.1 AWS Auto Scaling(CPU策略)

# 创建伸缩策略(AWS CLI)
aws autoscaling put-scaling-policy \
    --auto-scaling-group-name my-asg \
    --policy-name cpu-scale-out \
    --scaling-adjustment 2 \
    --adjustment-type ChangeInCapacity \
    --cooldown 120

# 创建CloudWatch告警
aws cloudwatch put-metric-alarm \
    --alarm-name cpu-high-alarm \
    --metric-name CPUUtilization \
    --namespace AWS/EC2 \
    --statistic Average \
    --period 60 \
    --evaluation-periods 2 \
    --threshold 75 \
    --comparison-operator GreaterThanThreshold \
    --alarm-actions arn:aws:autoscaling:...:policy/cpu-scale-out

这里有个细节:evaluation-periods 2 表示连续2个周期(共120秒)都超过阈值才触发。这能过滤掉短时尖峰。

4.4.2 阿里云ESS(内存策略)

# 创建伸缩规则(阿里云CLI)
aliyun ess CreateScalingRule \
    --ScalingGroupId asg-xxxx \
    --ScalingRuleName mem-scale-out \
    --ScalingRuleType SimpleScalingRule \
    --AdjustmentType QuantityChangeInCapacity \
    --AdjustmentValue 1 \
    --Cooldown 180

# 创建云监控报警
aliyun cms PutMetricRule \
    --RuleName mem-high-rule \
    --Namespace acs_ecs_dashboard \
    --MetricName memory_usedutilization \
    --Period 60 \
    --Statistics Average \
    --Threshold 80 \
    --ComparisonOperator GreaterThanThreshold \
    --EvaluationCount 3 \
    --ContactGroups my-group

你想想看,为什么阿里云这里我用了EvaluationCount 3?因为内存变化比CPU慢,多等一个周期更稳妥。

4.5 核心逻辑:一张图看懂

下面这张图,是我自己总结的动态伸缩决策流程。你照着这个思路配策略,基本不会出大问题。

动态伸缩决策流程 采集指标数据 CPU > 75% 或 内存 > 80%? (连续2个周期) 是 触发扩容 +2 实例,冷却 120s 否 CPU < 30% 且 内存 < 40%? (连续3个周期) 触发缩容 -1 实例,冷却 300s ⚠️ 关键设计要点 • 扩容用“或”逻辑,任一超标就扩 • 缩容用“与”逻辑,两个都低才缩 • 扩容冷却短(120s),缩容冷却长(300s) • 评估周期数:CPU用2,内存用3

4.6 避坑指南:我踩过的几个雷

  • 不要用单一数据点: 我曾经只采1分钟的数据,结果某次GC暂停导致CPU瞬间降到0,触发了缩容。后来改成取5分钟平均值,稳多了。
  • 注意“冷启动”问题: 新启动的实例需要预热。如果一启动就加入负载均衡,CPU会瞬间飙高,触发新一轮扩容。我一般给新实例加一个“预热期”,前2分钟不参与伸缩判断。
  • 缩容策略要保守: 缩容比扩容危险得多。扩容最多多花点钱,缩容可能导致服务过载。我习惯把缩容阈值设得比扩容阈值低很多(比如扩容75%,缩容25%),留足缓冲。
  • 别忘了“最大实例数”: 我见过有人没设上限,结果一次流量高峰弹出了200台机器,账单直接爆表。一定要设一个硬上限,比如最多20台。
一个小技巧: 如果你用的是Kubernetes,可以考虑HPA(Horizontal Pod Autoscaler)配合VPA(Vertical Pod Autoscaler)。HPA管数量,VPA管规格,两者配合能省更多钱。不过这是后面章节的内容了,这里先提一嘴。