4、弹性伸缩策略:水平扩展与垂直扩展、基于负载的自动伸缩、定时伸缩策略、伸缩冷却时间设置
弹性伸缩,说白了就是让系统能「自动长胖」或「自动减肥」。
我见过太多团队,一上来就买最高配的服务器,结果平时利用率不到10%。也见过一些团队,流量高峰来了系统直接崩掉,运维半夜爬起来手动加机器。这两种极端,都是因为没有做好弹性伸缩策略。
今天我们就来聊聊,怎么把这件事做得既省钱又靠谱。
4.1 水平扩展 vs 垂直扩展:先选对方向
先搞清楚两个基本概念。我个人习惯把它们叫做「加人」和「加饭」。
- 水平扩展(Scale Out/In):增加或减少服务器的数量。比如从3台变成10台。
- 垂直扩展(Scale Up/Down):给现有服务器升级或降级配置。比如从4核8G升级到16核32G。
你可能会问:哪个更好?嗯,这得看场景。
| 对比维度 | 水平扩展 | 垂直扩展 |
|---|---|---|
| 成本 | 按需购买,成本可控 | 升级到高配机器,单价贵 |
| 弹性速度 | 分钟级(启动新实例) | 秒级(重启即可) |
| 架构要求 | 需要无状态设计 | 对架构无特殊要求 |
| 上限 | 理论上无限 | 受限于物理机上限 |
| 适用场景 | Web服务、API网关 | 数据库、有状态服务 |
我在项目中遇到过一家电商公司,他们一开始只做垂直扩展。双十一流量上来,直接把服务器从8核升到64核。结果呢?单台机器扛住了,但一台挂了整个系统就瘫了。后来我帮他们改成水平扩展,虽然架构改起来费了点劲,但稳定性提升了一大截。
4.2 基于负载的自动伸缩:让系统自己决定
手动伸缩太累了。你想想看,半夜三点爬起来加机器,谁受得了?
所以我们要做自动伸缩。核心思路就一句话:设定阈值,让系统自己判断。
常见的触发指标有这些:
- CPU使用率:超过80%就加机器,低于30%就减机器
- 内存使用率:同上逻辑
- 请求响应时间:如果P99延迟超过500ms,说明压力大了
- 队列深度:消息队列积压太多,说明消费能力不够
- 并发连接数:连接数超过某个值,就该扩容了
举个例子,在AWS上用Auto Scaling Group配置:
# 创建伸缩组
aws autoscaling create-auto-scaling-group \
--auto-scaling-group-name my-web-asg \
--launch-template LaunchTemplateName=web-template \
--min-size 2 \
--max-size 10 \
--desired-capacity 2 \
--vpc-zone-identifier subnet-xxx,subnet-yyy
# 创建扩容策略:CPU超过70%持续5分钟,就加1台
aws autoscaling put-scaling-policy \
--auto-scaling-group-name my-web-asg \
--policy-name cpu-scale-out \
--scaling-adjustment 1 \
--adjustment-type ChangeInCapacity \
--cooldown 300
# 创建缩容策略:CPU低于30%持续10分钟,就减1台
aws autoscaling put-scaling-policy \
--auto-scaling-group-name my-web-asg \
--policy-name cpu-scale-in \
--scaling-adjustment -1 \
--adjustment-type ChangeInCapacity \
--cooldown 600
4.3 定时伸缩策略:可预测的流量,别浪费钱
有些流量是可以预测的。比如:
- 每天早上9点到10点,用户登录高峰
- 每周一上午,报表系统压力大
- 每月1号,账单生成任务
- 每年双十一、618大促
对于这些场景,用定时伸缩比用负载伸缩更划算。为什么?因为负载伸缩有滞后性——等CPU飙上去再扩容,用户已经感受到卡顿了。
定时伸缩的配置很简单:
# 每天早上8:30提前扩容,应对9点高峰
aws autoscaling put-scheduled-update-group-action \
--auto-scaling-group-name my-web-asg \
--scheduled-action-name morning-scale-up \
--start-time "2024-01-01T08:30:00Z" \
--min-size 5 \
--max-size 20 \
--desired-capacity 10
# 中午12:00缩容,午休时间流量低
aws autoscaling put-scheduled-update-group-action \
--auto-scaling-group-name my-web-asg \
--scheduled-action-name noon-scale-down \
--start-time "2024-01-01T12:00:00Z" \
--min-size 2 \
--max-size 10 \
--desired-capacity 3
我个人习惯的做法是:定时伸缩做「粗调」,负载伸缩做「微调」。比如大促期间,先用定时伸缩把基础容量从2台提到10台,然后让负载伸缩在10~50台之间自动调整。这样既保证了响应速度,又不会浪费资源。
4.4 伸缩冷却时间:别让系统「抽风」
冷却时间(Cooldown),是弹性伸缩里最容易忽略但又最重要的参数。
什么叫冷却时间?就是一次伸缩动作完成后,要等一段时间才能进行下一次伸缩。目的是防止系统「抽风」——刚加完机器,负载还没稳定下来,又触发了一次扩容。
我踩过这个坑。有一次给一个客户做配置,冷却时间设成了60秒。结果流量波动大,系统在5分钟内伸缩了8次。每次加机器要3分钟,缩机器要2分钟,整个集群一直在「加-缩-加-缩」的循环里打转。最后不仅没解决问题,还多花了不少钱。
冷却时间怎么设?我一般参考这几个原则:
| 场景 | 扩容冷却时间 | 缩容冷却时间 | 说明 |
|---|---|---|---|
| Web服务(轻量) | 120秒 | 300秒 | 缩容要更保守,避免频繁缩容 |
| 计算密集型任务 | 300秒 | 600秒 | 任务启动慢,冷却时间要长 |
| 数据库/缓存 | 600秒 | 900秒 | 有状态服务,伸缩代价大 |
| 大促期间 | 60秒 | 900秒 | 扩容要快,缩容要慢 |
4.5 综合策略:三种方式搭配使用
实际项目中,我不会只用一种策略。我的习惯是「三管齐下」:
- 定时伸缩做基础:根据历史流量规律,提前准备好基础容量
- 负载伸缩做补充:应对突发流量,在基础容量之上动态调整
- 冷却时间做保护:防止系统抖动,保证伸缩动作稳定
举个例子,一个典型的SaaS应用配置可能是这样的:
# 基础配置
MinSize: 2
MaxSize: 50
# 定时策略
08:00 -> DesiredCapacity: 5 # 上班前扩容
12:00 -> DesiredCapacity: 3 # 午休缩容
18:00 -> DesiredCapacity: 2 # 下班后缩容
# 负载策略
CPU > 70% 持续5分钟 -> +2台,冷却300秒
CPU < 30% 持续10分钟 -> -1台,冷却600秒
请求延迟 > 500ms 持续3分钟 -> +3台,冷却120秒
# 特殊日期(如月底)
每月最后一天 -> DesiredCapacity: 10,MaxSize: 100
这样配置下来,平时能省不少钱。我记得有个客户,原来固定跑20台机器,改成这套策略后,平时只跑3~5台,高峰期自动扩展到30台。一年下来,云成本降了60%多。