一条命令搞定 Nginx 高可用:AWS NLB 负载均衡完全指南

问题场景

你的网站放在一个 nginx 服务器上,业务增长后发现:

  • 单点故障风险高(服务器宕机 = 网站离线)
  • 流量突增时无法扩容
  • 无法做滚动更新(更新 nginx 配置时需要停机)

怎么办? 用 AWS Network Load Balancer(NLB)给 nginx 加一个"智能管家"。


🎯 核心方案(一句话)

在两个 nginx 实例前部署 NLB,让它自动分发流量、检测故障、智能转移。

互联网
  ↓
  🔷 NLB(固定入口点)
  ├→ 🟢 nginx-1(AZ-A)
  └→ 🟢 nginx-2(AZ-B)

📊 架构对比

❌ 旧架构:单点 Nginx

互联网 → nginx-1 → 网站
         (如果宕机 = 全死)

问题:

  • 单点故障
  • 无法扩容
  • 无法更新

✅ 新架构:NLB + 双 Nginx

互联网 → NLB(固定 DNS + IP)
        ├→ nginx-1(自动故障转移)
        └→ nginx-2(自动故障转移)

优势:

  • 高可用(一个宕机,自动切另一个)
  • 自动负载均衡
  • 零停机更新

🔧 部署步骤(实操)

第 1 步:准备两个 Nginx 实例

在两个**不同的可用区(AZ)**部署 nginx:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# AZ-A 中的 nginx-1
aws ec2 run-instances \
  --image-id ami-xxxxxxxx \
  --instance-type t3.medium \
  --subnet-id subnet-azA \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=nginx-1}]'

# AZ-B 中的 nginx-2
aws ec2 run-instances \
  --image-id ami-xxxxxxxx \
  --instance-type t3.medium \
  --subnet-id subnet-azB \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=nginx-2}]'

关键点: 一定要在不同 AZ,这样即使整个可用区宕机,服务也能继续。


第 2 步:创建 NLB

1
2
3
4
5
6
# 创建 NLB
aws elbv2 create-load-balancer \
  --name my-nlb \
  --subnets subnet-azA subnet-azB \
  --type network \
  --scheme internet-facing

输出示例:

LoadBalancerArn: arn:aws:elasticloadbalancing:us-east-1:xxx:loadbalancer/net/my-nlb/xxx
DNSName: my-nlb-xxx.elb.us-east-1.amazonaws.com

现在你有一个固定的 DNS 入口点了! 这个 DNS 永远不会变,即使后端实例换 IP。


第 3 步:创建目标组(Target Group)

NLB 需要知道要转发流量到哪些实例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 创建目标组
aws elbv2 create-target-group \
  --name nginx-targets \
  --protocol TCP \
  --port 80 \
  --vpc-id vpc-xxxxxxxx

# 将两个 nginx 实例加入目标组
aws elbv2 register-targets \
  --target-group-arn arn:aws:elasticloadbalancing:xxx:targetgroup/nginx-targets/xxx \
  --targets Id=i-nginx1 Id=i-nginx2

第 4 步:配置健康检查

这是关键!NLB 会自动检测 nginx 的健康状态,故障实例会自动被剔除:

1
2
3
4
5
6
7
8
aws elbv2 modify-target-group \
  --target-group-arn arn:aws:elasticloadbalancing:xxx:targetgroup/nginx-targets/xxx \
  --health-check-enabled \
  --health-check-protocol TCP \
  --health-check-port 80 \
  --healthy-threshold-count 3 \
  --unhealthy-threshold-count 3 \
  --health-check-interval-seconds 30

这是什么?

  • 每 30 秒检查一次 nginx 的 80 端口
  • 连续 3 次健康 → 流量转发到这个实例
  • 连续 3 次失败 → 停止转发(等待修复)

第 5 步:创建监听器(连接 NLB 和目标组)

1
2
3
4
5
aws elbv2 create-listener \
  --load-balancer-arn arn:aws:elasticloadbalancing:xxx:loadbalancer/net/my-nlb/xxx \
  --protocol TCP \
  --port 80 \
  --default-actions Type=forward,TargetGroupArn=arn:aws:elasticloadbalancing:xxx:targetgroup/nginx-targets/xxx

大功告成! 现在:

  • 流量进来 → NLB 接收
  • NLB 根据健康检查的结果 → 分发到 nginx-1 或 nginx-2
  • 其中一个故障 → 自动全部转移到另一个

📊 工作流程图解

正常状态

用户请求 → NLB
            ├→ nginx-1(✅ 健康,接收 50% 流量)
            └→ nginx-2(✅ 健康,接收 50% 流量)

nginx-1 故障

用户请求 → NLB
            ├→ nginx-1(❌ 故障,不转发)
            └→ nginx-2(✅ 健康,接收 100% 流量)
             
[NLB 自动检测故障,无需人工干预]

nginx-1 恢复

用户请求 → NLB
            ├→ nginx-1(✅ 恢复,接收 50% 流量)
            └→ nginx-2(✅ 健康,接收 50% 流量)

[自动恢复,无需重启]

💡 高级用法

1. 跨区域容错

当前架构: 两个 AZ(区域 A 和区域 B)

  • 区域 A 宕机 → 自动切到区域 B ✅
  • 区域 B 宕机 → 自动切到区域 A ✅
  • 两个都宕机 → 没救了 ❌

更强大的架构: 三个 AZ(区域 A / B / C)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 在第三个 AZ 部署
aws ec2 run-instances \
  --image-id ami-xxxxxxxx \
  --instance-type t3.medium \
  --subnet-id subnet-azC

# 加入 NLB
aws elbv2 register-targets \
  --target-group-arn arn:aws:elasticloadbalancing:xxx:targetgroup/nginx-targets/xxx \
  --targets Id=i-nginx3

2. 监控和告警

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 当有实例不健康时发告警
aws cloudwatch put-metric-alarm \
  --alarm-name nginx-unhealthy \
  --alarm-description "Alert when nginx is unhealthy" \
  --metric-name UnHealthyHostCount \
  --namespace AWS/NetworkELB \
  --statistic Average \
  --period 60 \
  --threshold 1 \
  --comparison-operator GreaterThanOrEqualToThreshold \
  --alarm-actions arn:aws:sns:us-east-1:xxx:my-topic

3. 流量分布调整

想让某个实例承载更多流量?使用权重:

1
2
3
4
5
aws elbv2 modify-target-group-attributes \
  --target-group-arn arn:aws:elasticloadbalancing:xxx:targetgroup/nginx-targets/xxx \
  --attributes \
    Key=stickiness.enabled,Value=true \
    Key=stickiness.type,Value=source_ip

⚠️ 常见问题

Q1: NLB 会不会单点故障?

A: 不会!NLB 自身已经是高可用的(多 AZ 部署),AWS 管理。

Q2: NLB 成本贵吗?

A: 按 LCU(Load Balancer Capacity Unit)计费,通常 $0.006/LCU/小时。

  • 小流量:$5-10/月
  • 中等流量:$20-50/月

Q3: 如何做到零停机更新 nginx 配置?

A: 使用连接池排空(connection draining):

1
2
3
aws elbv2 modify-target-group-attributes \
  --target-group-arn arn:aws:elasticloadbalancing:xxx:targetgroup/nginx-targets/xxx \
  --attributes Key=deregistration_delay.timeout_seconds,Value=30

现在:

  1. 更新 nginx-1 配置
  2. NLB 自动停止向 nginx-1 发送新连接
  3. 现有连接完成(最多 30 秒)
  4. nginx-1 重启
  5. 完全透明,用户零感知

Q4: 可以同时支持 HTTP 和 HTTPS 吗?

A: 可以!创建两个监听器:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# HTTP 监听器
aws elbv2 create-listener \
  --load-balancer-arn arn:aws:elasticloadbalancing:xxx:loadbalancer/net/my-nlb/xxx \
  --protocol TCP \
  --port 80 \
  --default-actions Type=forward,TargetGroupArn=xxx

# HTTPS 监听器
aws elbv2 create-listener \
  --load-balancer-arn arn:aws:elasticloadbalancing:xxx:loadbalancer/net/my-nlb/xxx \
  --protocol TLS \
  --port 443 \
  --certificates CertificateArn=arn:aws:acm:xxx \
  --default-actions Type=forward,TargetGroupArn=xxx

📋 快速部署清单

  • 准备两个 nginx 实例(不同 AZ)
  • 创建 NLB
  • 创建目标组
  • 配置健康检查
  • 创建监听器
  • 测试故障转移(关闭一个 nginx,看流量是否自动转移)
  • 配置告警
  • 切换 DNS 到 NLB

🎯 效果验证

部署完成后,你的网站:

高可用:单个 nginx 宕机不影响服务 ✅ 自动故障转移:秒级切换 ✅ 可扩展:需要更多容量时,直接加更多 nginx 实例 ✅ 零停机更新:更新配置时用户无感知 ✅ 自动负载均衡:流量均匀分发


📊 对比表

方案单点 NginxNLB + 双 Nginx
可用性99%99.99%
故障转移时间N/A(宕机就死)< 30 秒自动
可扩展性无(单机上限)有(加实例即可)
零停机更新❌ 不行✅ 可以
月成本~$0~$20-50

💰 成本分析

月度成本估算(假设日均 1000 万请求):

项目成本
NLB 基础费$16.20
LCU 费用$30-50
两个 EC2 实例(t3.medium)$30-40
总计约 $80-110/月

vs 单点 Nginx($30-40/月):

  • 多付 $50-70/月
  • 换来 99.99% 可用性和零停机更新
  • 非常值得!

🚀 总结

一句话: 用 AWS NLB 给两个 nginx 加一个"智能管家",自动分发流量、检测故障、智能转移。

三个要点:

  1. 跨 AZ 部署两个 nginx(提高可用性)
  2. NLB 自动做健康检查和故障转移
  3. DNS 指向 NLB,一劳永逸

一条命令启动高可用:

1
2
# 参考上面的 5 个步骤,按顺序执行
# 从第 1 步到第 5 步,30 分钟搞定

下一步? 选择你的架构,开始部署吧!💪

如果有问题,欢迎留言讨论。