弹性伸缩与 ELB — CodeRoadMap弹性伸缩与 ELB
这一课你将能做到
- 创建一个跨两个 AZ 的 Application Load Balancer,并配置目标组和健康检查
- 配置 Auto Scaling Group(ASG),实现根据 CPU 负载自动扩缩容
- 说出 ALB、NLB、CLB 三种负载均衡器的区别,并能选出适合本站场景的方案
为什么要学
本站目前部署在阿里云,如果有流量高峰(比如上了热门推荐),后端服务器可能扛不住。AWS 的 ELB + ASG 是自动扩缩容的标准答案。面试中「你们怎么应对高并发」「负载均衡是怎么做的」「自动伸缩策略怎么配的」是高频问题。
人话:负载均衡器就像餐厅的前台,客人来了自动分流到各个厨师(后端服务器)。如果客人突然变多,弹性伸缩就像自动叫来更多厨师;客人少了,多余的厨师自动下班。
先建立图像
ELB + ASG 架构图:
Internet
│
┌─────┴─────┐
│ ALB │ ←── 跨 AZ,做 HTTP/HTTPS 转发
│(监听:80/443)│
└─────┬─────┘
│
┌─────────────┼─────────────┐
│ │ │
┌────┴────┐ ┌────┴────┐ ┌────┴────┐
│ AZ-1a │ │ AZ-1b │ │ 自动扩容 │
│ EC2 ×2 │ │ EC2 ×2 │ │(ASG) │
│ │ │ │ │ │
└─────────┘ └─────────┘ └─────────┘
│ │ │
└─────────────┴─────────────┘
│
┌─────┴─────┐
│ RDS │ ←── 私有子网,数据层
│ 主/备 │
└───────────┘
三种负载均衡器对比:
| 类型 | 层级 | 协议 | 特点 | 本站场景 |
|---|
| CLB | 经典(旧) | HTTP/HTTPS/TCP | 功能少,不建议用 | 不选 |
| ALB | 应用层(L7) | HTTP/HTTPS/GRPC | 基于路径/主机名路由 | 本站首选 |
| NLB | 传输层(L4) | TCP/TLS/UDP | 高性能、低延迟 | 游戏、IoT |
跟着做
步骤 1:创建目标组
# 创建目标组(HTTP 8080)
aws elbv2 create-target-group --name codenav-tg --protocol HTTP --port 8080 --vpc-id vpc-xxxxxxxx --health-check-path "/actuator/health" --health-check-interval-seconds 30
# 记录返回的 TargetGroupArn
步骤 2:创建 Application Load Balancer
# 创建 ALB(公有子网)
aws elbv2 create-load-balancer --name codenav-alb --subnets subnet-public1a subnet-public1b --security-groups sg-albxxxx --scheme internet-facing --type application --ip-address-type ipv4
# 创建监听器(HTTP 80 → 目标组)
aws elbv2 create-listener --load-balancer-arn arn:aws:elasticloadbalancing:ap-southeast-1:123456789012:loadbalancer/app/codenav-alb/xxxxxxxx --protocol HTTP --port 80 --default-actions Type=forward,TargetGroupArn=arn:aws:elasticloadbalancing:ap-southeast-1:123456789012:targetgroup/codenav-tg/xxxxxxxx
步骤 3:创建启动模板(Launch Template)
# 创建启动模板(用之前建好的 AMI 和 IAM Role)
aws ec2 create-launch-template --launch-template-name codenav-lt --launch-template-data '{
"ImageId": "ami-xxxxxxxx",
"InstanceType": "t3.small",
"KeyName": "codenav-key",
"SecurityGroupIds": ["sg-appxxxx"],
"IamInstanceProfile": {"Arn": "arn:aws:iam::123456789012:instance-profile/codenav-ec2-profile"},
"UserData": "IyEvYmluL2Jhc2gKc3VkbyBkbmYgaW5zdGFsbCBqYXZhLTE3LWFtYXpvbi1jb3JyZXR0byAteQpjZCAvaG9tZS9lYzItdXNlcgpudW1ib29wIGphdmEgLWphciBjb2RlLW5hdi0wLjAuMS1TTkFQU0hPVC5qYXIgPWFwcC5sb2cgMj4mMSAmCg=="
}'
UserData 是 base64 编码的启动脚本,内容是装 Java 并启动 jar 包。
步骤 4:创建 Auto Scaling Group
# 创建 ASG(最小 2 台,最大 6 台,跨两个私有子网)
aws autoscaling create-auto-scaling-group --auto-scaling-group-name codenav-asg --launch-template LaunchTemplateName=codenav-lt,Version=1 --min-size 2 --max-size 6 --desired-capacity 2 --vpc-zone-identifier subnet-private1a,subnet-private1b --target-group-arns arn:aws:elasticloadbalancing:ap-southeast-1:123456789012:targetgroup/codenav-tg/xxxxxxxx --health-check-type ELB --health-check-grace-period 300
步骤 5:配置扩缩容策略
# 创建 Scale Out 策略(CPU > 60% 时加 1 台)
aws autoscaling put-scaling-policy --auto-scaling-group-name codenav-asg --policy-name codenav-scale-out --policy-type TargetTrackingScaling --target-tracking-configuration file://target-tracking.json
{
"PredefinedMetricSpecification": {
"PredefinedMetricType": "ASGAverageCPUUtilization"
},
"TargetValue": 60.0,
"ScaleOutCooldown": 300,
"ScaleInCooldown": 300
}
步骤 6:验证扩缩容
# 查看 ASG 状态
aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names codenav-asg
# 查看目标组健康状态
aws elbv2 describe-target-health --target-group-arn arn:aws:elasticloadbalancing:ap-southeast-1:123456789012:targetgroup/codenav-tg/xxxxxxxx
# 用 ab 或 wrk 压测,触发扩容
ab -n 10000 -c 100 http://codenav-alb-xxxxxxxx.ap-southeast-1.elb.amazonaws.com/
讲清楚要点
- 健康检查(Health Check):ALB 定期向后端发 HTTP 请求(默认路径
/),如果连续失败就标记为 unhealthy,停止转发流量。必须配一个真实存在的健康端点,如 Spring Boot 的 /actuator/health。
- 目标组(Target Group):ALB 不直接绑定实例,而是绑定目标组。目标组里可以放 EC2、Lambda、IP 地址。解耦后容易换后端。
- Launch Template vs Launch Configuration:Launch Configuration 是老版本,不支持混用实例类型。Launch Template 功能更强,支持 T2/T3 无限模式、混合实例策略,是新项目的首选。
- Cooldown(冷却时间):扩容/缩容后等待一段时间再评估,防止震荡。Scale Out 冷却通常 5 分钟,Scale In 冷却可以更长(避免新机器刚上来就被删掉)。
- 混合实例策略(Mixed Instances Policy):ASG 可以同时配置 On-Demand 和 Spot 实例,比如 40% On-Demand(稳定)+ 60% Spot(省钱),系统会自动分配。
你可能会懵的地方
-
ALB 和 NLB 到底选哪个?
HTTP/HTTPS 用 ALB,它能做路径路由、主机名路由、HTTPS 终结、粘性会话。TCP/UDP 或需要固定 IP 的用 NLB。本站是 Spring Boot HTTP 服务,选 ALB。
-
ASG 的 Desired Capacity 到底听谁的?
手动设置、定时策略、预测式策略、目标追踪策略同时存在时,AWS 选最大的那个。手动改 Desired Capacity 后,目标追踪策略可能在一段时间后把它改回来。
-
ELB 为什么收费?
ALB 按 Load Balancer Capacity Units(LCU)收费,包括新连接数、活跃连接数、处理流量、规则评估四个维度。小流量约 $0.022/小时,LCU 用得多再额外计费。
-
ALB 能直接挂在公有子网吗?
必须放在公有子网,因为 ALB 要接 IGW 的入站流量。后端 EC2 放私有子网即可。
-
Spot 实例适合放在 ASG 里吗?
适合,但要做好被中断的准备。Spot 实例在价格飙升或容量不足时会被 AWS 回收(2 分钟警告)。非关键业务(如批处理、CI/CD 构建)适合用 Spot。
错法对照
| 错法 | 问题 | 正解 |
|---|
健康检查路径配成 / | 如果 / 有业务逻辑,可能被防火墙拦 | 配专用健康端点,如 /health 或 /actuator/health |
| ASG 最大容量设太大 | 流量攻击或被压测时,账单爆炸 | 按预算设上限,配合预算告警 |
| 只在一个 AZ 部署 | 单点故障 | 至少跨两个 AZ,ALB 会自动跨 AZ 分发 |
| 缩容策略太激进 | 请求处理一半被中断 | 用 Lifecycle Hook,让实例先优雅停机 |
| 不用启动模板用启动配置 | 启动配置已被标记为弃用 | 用 Launch Template,功能更全 |
卡点急救
- ALB 返回 502 Bad Gateway:后端实例健康检查失败,或者安全组不允许 ALB 访问后端端口。检查安全组入站规则,确保 ALB 安全组能访问目标组的端口。
- ASG 不断创建和终止实例:健康检查失败,新实例还没起来就被标记为不健康。检查 UserData 是否正确执行、应用是否启动、健康端点是否可访问。
- 扩容太慢,流量高峰扛不住:用预热(Warm Pools)或提前扩容(Scheduled Scaling)。目标追踪策略的反应时间约 2-5 分钟,突发流量可以先人工提 Desired Capacity。
面试常问
-
ALB 和 NLB 的区别?为什么选 ALB?
ALB 是 L7 负载均衡器,支持基于 HTTP 头部、路径、主机名的路由,支持 WebSocket、gRPC,适合 Web 应用。NLB 是 L4 负载均衡器,性能更高、延迟更低,支持 TCP/UDP 和静态 IP。本站是 Spring Boot HTTP 服务,用 ALB。
-
Auto Scaling 的触发条件有哪些?
目标追踪(CPU/内存/自定义指标)、步进策略(按指标区间加不同数量)、定时策略(预测高峰)、预测式策略(机器学习预测)。
-
怎么保证扩容时用户会话不丢失?
不要把 Session 存在单机内存里,用 ElastiCache(Redis)或 DynamoDB 存 Session。或者用 ALB 的粘性会话(Session Stickiness),但粘性会话会破坏负载均衡效果,不推荐。
自测三问
- 如果健康检查路径返回 404,ALB 会怎么处理这台实例?
- Launch Template 相比 Launch Configuration 增加了哪些能力?
- 为什么 ALB 必须放在公有子网,而后端 EC2 可以放在私有子网?
小结一句话
ELB 分流、ASG 弹性,健康检查是生命线,跨 AZ 是底线,目标追踪策略是最省心的扩缩容方式。
延伸