Skip to content

负载均衡与网关

🎯 核心问题

当单台服务器扛不住时,如何把流量"聪明地"分配到多个服务器实例? 负载均衡是现代分布式系统的"分发员"。本文通过真实案例(奶茶店收银、快递分拣、交通指挥)深入理解负载均衡的设计哲学和工程实践。


1. 为什么要"负载均衡"?

1.1 从一个真实案例说起:某网站的架构演进

某创业公司在用户量快速增长时遇到了严重的性能问题:

场景还原:

阶段一:单台服务器
用户 → 服务器(1核2G)

  日活1000 → 活跃时间:1000人同时访问

问题:CPU 100%,响应慢,经常宕机

⚠️ 单台服务器的致命问题

  • 性能瓶颈: CPU 100%,响应时间> 5秒
  • 单点故障: 服务器挂了,整个网站不可用
  • 扩展困难: 只能垂直升级(加CPU、内存),贵且有限

改进后的架构(引入负载均衡):

阶段二:多台服务器 + 负载均衡
用户 → 负载均衡器(Nginx)

     ├→ 服务器1 (1核2G)
     ├→ 服务器2 (1核2G)
     └→ 服务器3 (1核2G)

✨ 改进后的效果

  • 性能提升: 3台服务器并行处理,响应时间< 1秒
  • 高可用: 1台服务器挂了,其他服务器继续服务
  • 水平扩展: 需要更多性能?加服务器就行

1.2 负载均衡的生活化比喻

奶茶店收银台

想象你开了一家网红奶茶店:

  • 1个收银台: 顾客排队,后面的人等不及,差评
  • 3个收银台: 员工分配顾客到不同收银台,效率提升3倍

负载均衡就是"收银台分配员":

  • 用户(顾客) → 请求服务
  • 负载均衡器(分配员) → 把请求分配到不同服务器
  • 服务器(收银台) → 处理请求
负载均衡器类型
从四层到七层,从硬件到软件的演进
传统架构单点
🖥️
Web Server
负载: 95% 🔥
负载均衡架构分布式
⚖️L4 Load Balancer
🖥️
S1
🖥️
S2
🖥️
S3
📦四层负载均衡 (L4)
工作原理

基于传输层信息(IP地址+端口)进行流量分发。不关心应用层内容,只做"快递分拣",因此性能极高。

典型产品
LVS (Linux Virtual Server)HAProxy (TCP模式)AWS NLBAzure Load Balancer
适用场景
  • 需要极高吞吐量的场景
  • TCP/UDP流量分发
  • 不需要内容识别的场景
  • 微服务间通信
性能对比一览
类型
处理层
性能
灵活性
成本
硬件负载均衡
L4/L7
$$$$$
四层负载均衡
L4 (传输层)
$$
七层负载均衡
L7 (应用层)
$$$
软件负载均衡
L4/L7
$

2. 什么是负载均衡?

2.1 四层负载均衡(L4):只看门牌号

工作在传输层(TCP/UDP),就像快递小哥只看你家的门牌号(IP地址+端口号),不关心你家是做什么。

特点:

  • 速度超快: 只做简单的地址转发,不解析数据包内容
  • 适用场景: 数据库连接、Redis缓存、长连接游戏服务器
  • 代表产品: LVS(Linux Virtual Server)、AWS NLB、Azure Load Balancer
工作原理
客户端请求 → L4负载均衡器 → 后端服务器

         只看IP + Port

         快速转发(不解包内容)

2.2 七层负载均衡(L7):检查包裹内容

工作在应用层(HTTP/HTTPS),就像快递小哥不仅看门牌号,还会打开包裹检查内容,根据内容决定怎么送。

特点:

  • 智能路由: 可以根据URL路径、HTTP头、Cookie等做精细化路由
  • 高级功能: SSL卸载、内容缓存、压缩、安全WAF
  • 适用场景: Web应用、API网关、微服务架构
  • 代表产品: Nginx、HAProxy、AWS ALB、Envoy
工作原理
客户端请求 → L7负载均衡器 → 解析HTTP内容

         检查URL、Header、Cookie

         智能路由到特定服务器

2.3 L4 vs L7 对比一览

维度四层负载均衡(L4)七层负载均衡(L7)
工作层级传输层(TCP/UDP)应用层(HTTP/HTTPS)
决策依据IP地址 + 端口号URL、Header、Cookie、Body
处理速度极快(内核态处理)较快(用户态解析)
功能丰富度基础转发SSL卸载、缓存、压缩、WAF
典型场景数据库、游戏、长连接Web应用、API网关、微服务
代表产品LVS、AWS NLBNginx、HAProxy、AWS ALB

3. 核心问题一:如何避免"坏掉"的服务器继续接客?

3.1 健康检查:别让"生病"的服务器拖累系统

想象一下,你的某个收银台突然坏了,但分配员不知道,还在源源不断地把顾客分过去。结果队伍越来越长,顾客怨声载道。

健康检查(Health Check)就是防止这种情况发生的"哨兵"。它定期"体检"每台服务器,发现"生病"的立即从队列中移除,等"康复"了再请回来。

3.2 主动健康检查 vs 被动健康检查

主动健康检查(Active Health Check): 负载均衡器主动"敲门"问服务器"你还在吗?"

  • 定期发送探测请求(如 HTTP /health、TCP ping)
  • 响应超时或返回错误码则认为不健康
  • 优点: 检测结果准确可靠
  • 缺点: 产生额外的探测流量

被动健康检查(Passive Health Check): 负载均衡器"观察"真实业务流量的响应情况

  • 统计实际请求的响应时间、错误率
  • 连续多次失败则认为不健康
  • 优点: 不产生额外流量
  • 缺点: 需要足够的流量样本才能判定
阈值设定表
指标健康阈值不健康阈值说明
HTTP状态码200-399400+或超时4xx/5xx都认为失败
TCP连接成功建立连接超时检查端口是否可达
响应时间< 500ms> 2000ms超时时间通常设为2-5秒
连续失败次数-3次避免单次抖动误判
检查间隔-5s太频繁会增加负载

💡 踸见坑:阈值设置太"敏感"

某团队将健康检查的响应时间阈值设为100ms,而他们的应用平均响应时间在80-120ms之间波动。结果是服务器频繁被标记为"不健康",导致流量在健康和不健康之间反复横跳,系统整体可用率反而下降。

正确的做法: 阈值应该设置为P99响应时间的2-3倍,给正常波动留出足够的缓冲空间。


4. 核心问题二:如何保证"老顾客"一直找同一个"收银员"?

4.1 会话保持:让"老顾客"一直找同一个"收银员"

想象你是奶茶店的常客,每次来都由同一个店员接待。她知道你的口味偏好(半糖、去冰),服务起来又快又贴心。但如果每次来都换一个新人,你得一遍遍重复同样的要求,效率大打折扣。

会话保持(Session Persistence/Sticky Session) 就是解决这个问题的方法:确保同一个用户的请求,始终被路由到同一台后端服务器。

会话保持机制
Cookie、IP哈希与粘性会话的技术对比
应用场景:
👤
用户A
👥
用户B
👨‍💼
用户C
请求
⚖️负载均衡器
🍪
Cookie 插入
通过HTTP Cookie保持会话
会话映射表
sess_abc123Server 1
sess_def456Server 2
sess_ghi789Server 1
🖥️
Server 1
10.0.1.10
选中
🖥️
Server 2
10.0.1.11
🖥️
Server 3
10.0.1.12
三种会话保持机制对比
🍪Cookie 插入
不受客户端IP变化影响
首次请求即可保持会话
客户端需支持Cookie
存在Cookie被禁用的风险
#️⃣IP Hash
无需客户端支持任何机制
无状态,LB重启不影响会话
客户端IP变化会丢失会话
难以做到真正的负载均衡
📝粘性会话
结合Cookie和IP两种方式优势
支持会话复制和故障转移
实现复杂,需要应用支持
会话复制带来性能开销

4.2 三种会话保持机制对比

机制实现原理优点缺点适用场景
Cookie插入LB在响应中插入Cookie,后续请求携带此Cookie不受IP变化影响,首次请求即可保持客户端需支持Cookie,可能被禁用电商购物车、登录态保持
IP哈希对客户端IP做哈希计算,映射到特定服务器无需客户端支持,无状态IP变化会丢失会话,难以均匀分布无Cookie环境、WebSocket
粘性会话表LB维护会话到服务器的映射表支持会话复制和故障转移占用LB内存,需要额外同步高可用要求严格的场景

💡 使用建议

  • Cookie插入: 优先推荐,兼容性好
  • IP哈希: 只用于WebSocket等特殊场景
  • 粘性会话表: 配合Cookie,提供故障转移能力

5. 核心问题三:如何实现零停机部署?

5.1 蓝绿部署:"一键切换"的零停机发布

核心思想: 同时维护两套完全相同的生产环境(蓝环境和绿环境),但只有一个环境对外提供服务。

蓝绿部署
零停机发布的经典策略,两套环境瞬间切换
🔵
蓝环境
v1.0.0
100% 流量
🟢
绿环境
v1.1.0
0% 流量
用户流量
👤
👤
👤
👤
👤
⚖️
负载均衡器
当前指向: 🔵 蓝环境
🔵蓝环境v1.0.0
🖥️B1
🖥️B2
🖥️B3
🟢绿环境v1.1.0
🖥️G1
🖥️G2
🖥️G3
蓝绿部署流程
1
绿环境部署
在绿环境部署新版本,进行冒烟测试
2
切换流量
将负载均衡器指向绿环境,流量瞬间切换
3
监控观察
观察绿环境运行状态,确认无异常
4
蓝环境升级
在蓝环境部署新版本,为下次切换做准备
蓝绿部署优缺点
优点
  • 零停机时间:流量切换在毫秒级完成,用户无感知
  • 快速回滚:发现问题可立即切回原环境,风险可控
  • 完整的预发布测试:新环境可完整测试后再接管流量
  • 数据一致性:无需处理新旧版本同时运行时的兼容问题
缺点
  • 资源成本高:需要同时维护两套完整环境,服务器成本翻倍
  • 数据库兼容性挑战:如果涉及数据库Schema变更,需要特别处理兼容性
  • 预热问题:新环境启动后可能需要时间预热缓存、连接池等
  • 不适合有状态服务:对于长连接、会话保持要求高的场景处理复杂

工作流程:

  1. 初始状态: 蓝环境运行v1.0(生产),绿环境待命。
  2. 部署新版本: 在绿环境部署v1.1,进行内部冒烟测试。
  3. 切换流量: 将负载均衡器指向绿环境,流量瞬间切换到v1.1。
  4. 监控观察: 观察绿环境运行状态,确认无异常。
  5. 保留旧版本: 蓝环境保持v1.0一段时间(如24小时),作为快速回滚的保险。

✨ 优缺点分析

优点缺点
✅ 零停机时间,切换在毫秒级完成❌ 资源成本高,需要同时维护两套环境
✅ 快速回滚,发现问题立即切回原环境❌ 数据库Schema变更时需要特别处理兼容性
✅ 新环境可完整测试后再接管流量❌ 不适用于有状态服务(如WebSocket长连接)

5.2 金丝雀发布:"小步快跑"的灰度策略

金丝雀发布得名于历史上的"煤矿金丝雀"——矿工带着金丝雀下井,如果金丝雀出现异常,说明有毒气体泄漏,矿工立即撤离。在软件发布中,金丝雀发布就是先让一小部分用户试用新版本,观察没有问题后再逐步扩大范围。

金丝雀发布
灰度发布策略,小流量先行验证新版本
流量分配比例拖动滑块调整新旧版本流量占比
稳定版 v1.0.090%
金丝雀 v1.1.010%
实时流量模拟 总请求: 0 | 稳定版: 0 | 金丝雀: 0
用户请求
负载均衡器
⚖️
Canary:10%
后端服务
稳定版 v1.0.0
📦S1
📦S2
📦S3
金丝雀 v1.1.0
🧪C1
🧪C2
金丝雀发布最佳实践
📊渐进式放量
  • 1% → 5% → 10% → 25% → 50% → 100%
  • 每个阶段观察至少15-30分钟
  • 关键指标:错误率、延迟、吞吐量
🎯精准用户选择
  • 内部员工/测试用户先行
  • 按地域:选择特定区域用户
  • 按用户属性:VIP用户或普通用户
  • 按设备类型:iOS/Android/Web
🛡️自动回滚机制
  • 错误率超过阈值自动回滚
  • P99延迟异常触发告警
  • 关键业务指标下降自动回滚
  • 一键回滚:30秒内恢复旧版本
📈监控与指标
  • 基础设施:CPU、内存、磁盘、网络
  • 应用指标:QPS、错误率、延迟分布
  • 业务指标:转化率、订单量、收入
  • 用户体验:页面加载时间、交互延迟

核心思想:

  1. 小流量先行: 先将1%的流量导入新版本服务器。
  2. 观察指标: 持续监控错误率、延迟、业务关键指标。
  3. 逐步放量: 如果一切正常,逐步将比例提升到5%、10%、25%、50%、100%。
  4. 快速回滚: 一旦发现异常,立即将所有流量切回旧版本。

💡 金丝雀发布的优势

优势说明
🎯 风险可控即使新版本有严重Bug,也只影响少量用户
📊 真实验证在真实生产环境验证,比测试环境更可靠
🚀 快速迭代团队可以更自信地频繁发布新功能
💰 资源友好不需要像蓝绿部署那样准备两套完整环境

6. 核心问题四:如何让系统自己"呼吸"?

6.1 自动扩缩容:让系统像餐厅一样"灵活排班"

想象你开了一家餐厅:

  • 午餐高峰期: 需要10个服务员,但下午3点闲时只需要2个
  • 如果一直维持10个**: 人工成本爆炸
  • 如果一直只有2个: 高峰期顾客等不及,全跑了

自动扩缩容(Auto Scaling) 就是让系统像餐厅一样"灵活排班"——忙的时候自动加服务器,闲的时候自动减服务器。

自动扩缩容
基于CPU、内存、QPS的智能弹性伸缩
扩容指标:
实时监控 实时
💻CPU使用率
45%
扩容阈值: 70%缩容阈值: 30%
🧠内存使用率
60%
扩容阈值: 75%缩容阈值: 40%
QPS
650req/s
扩容阈值: 1000/s目标: 800/s
🖥️运行实例
3个实例
最小: 2最大: 10
1
2
3
4
5
6
7
8
9
10
扩缩容历史最近 5 次操作
📈
扩容: 2 → 3 实例
CPU使用率超过70%
10:23
📉
缩容: 4 → 3 实例
CPU使用率低于30%
09:15
📈
扩容: 3 → 4 实例
QPS达到1000/s
08:42
📈
扩容: 2 → 3 实例
内存使用率超过75%
07:30
📉
缩容: 5 → 4 实例
流量下降
06:20
自动扩缩容最佳实践
⏱️
冷却时间
设置适当的冷却时间(通常3-5分钟),避免扩缩容操作过于频繁导致的震荡
📊
多指标综合
不要依赖单一指标,结合CPU、内存、QPS、连接数等多维度进行综合判断
🎯
目标利用率
设置合理的资源目标利用率(如70%),预留足够的缓冲应对突发流量
快速扩容
扩容操作应该比缩容更激进,确保系统能快速应对流量增长

6.2 扩容指标的选择

自动扩缩容的核心是回答一个问题:** 什么时候该加机器?什么时候该减机器?

常见的决策指标:

指标扩容阈值缩容阈值适用场景
CPU使用率> 70%< 30%计算密集型应用
内存使用率> 75%< 40%内存密集型应用
QPS(每秒请求数)> 1000/s< 400/sAPI网关、Web服务
连接数> 5000< 1000数据库、消息队列
自定义业务指标视业务而定视业务而定特定业务场景

💡 扩容策略的"坑"与"解"

坑1:扩容反应太慢,流量洪峰已经把系统打挂了

某电商大促期间,设置CPU > 80%触发扩容,但监控采集有1分钟延迟,新实例启动需要3分钟。结果流量来得太快,扩容还没完成,服务器已经被打挂。

解决方案:

  • 提前扩容: 基于历史数据预测流量高峰,提前30分钟开始扩容
  • 多级阈值: 设置60%预警(开始预热新实例)、70%正式扩容、80%紧急扩容
  • 快速扩容: 使用容器化部署,新实例30秒内启动(相比虚拟机3-5分钟)

坑2:扩容太激进,成本爆炸

某创业公司设置了激进的自动扩容策略:CPU > 50%就扩容。结果一个正常的业务波动就触发了扩容,服务器数量从5台膨胀到30台,月底云账单吓哭了CTO。

解决方案:

  • 设置扩容冷却时间: 一次扩容后,至少等待5分钟才能再次扩容
  • 设置最大实例数: max = 当前实例数 × 2,防止无限膨胀
  • 区分突刺和趋势: 只有连续3个周期都超过阈值才扩容,避免单点突刺触发

坑3:缩容太快,刚扩容的机器马上就缩了

某团队设置了CPU < 30%缩容。扩容后流量还在消化,CPU短暂回落到25%,触发了缩容。刚缩完CPU又飙到80%,又触发扩容——系统在"扩容-缩容-扩容"中疯狂震荡。

解决方案:

  • 缩容更保守: 扩容阈值70%,缩容阈值25%,中间有足够的缓冲带
  • 缩容冷却时间更长: 扩容后至少等待10分钟才能缩容
  • 渐进式缩容: 一次只缩1台,观察后再决定要不要继续缩

7. 实战:如何选择负载均衡器?

7.1 主流负载均衡器对比

特性NginxHAProxyEnvoy云厂商负载均衡
定位高性能反向代理/负载均衡开源负载均衡云原生代理托管负载均衡
性能极高(C语言,事件驱动)高(事件驱动)高(C++/Rust)极高
功能丰富度基础负载均衡、静态文件、缓存丰富的负载均衡算法高级路由、观测功能全面
配置配置文件(nginx.conf)配置文件(haproxy.cfg)API/配置文件UI控制台
扩展C模块/Lua脚本Lua脚本WASM/Filter插件
适用场景静态资源、七层负载均衡、SSL终结七层负载均衡、高可用服务网格、多云快速上手

💡 选型建议

决策树:

选择负载均衡器:

├─ 只需要基础的四层负载均衡?
│  ├─ 是 → LVS(开源免费)或 云厂商NLB
│  └─ 否 → 继续

├─ 需要服务网格、多云部署?
│  ├─ 是 → Envoy
│  └─ 否 → 继续

├─ 需要极其复杂的配置和插件?
│  ├─ 是 → HAProxy
│  └─ 否 → 继续

├─ 需要高性能+简单配置?
│  ├─ 是 → Nginx(首选)
│  └─ 继续

├─ 想要托管运维?
│  ├─ 是 → 云厂商负载均衡(AWS ALB、阿里SLB)
│  └─ Nginx自建

8. 总结:负载均衡的核心思维

8.1 核心原则回顾

原则含义实践要点
分层L4处理"快递分拣"(快但简单)L4处理数据库、游戏;L7处理Web、API
冗余单点故障是架构的敌人通过多实例、多区域部署提升可用性
渐进发布新版本不要"一刀切"蓝绿部署实现零停机;金丝雀实现风险可控
弹性系统应该像生命体一样"呼吸"忙时自动扩容,闲时自动缩容

8.2 设计检查清单

在引入负载均衡前,问自己以下问题:

  • [ ] 是否真的需要负载均衡?(单机性能是否真的不够)
  • [ ] 选择L4还是L7?(根据业务场景)
  • [ ] 如何处理会话保持?(Cookie、IP哈希、会话表)
  • [ ] 如何实现健康检查?(主动、被动、阈值设置)
  • [ ] 如何实现零停机?(蓝绿部署、金丝雀)
  • [ ] 如何实现弹性?(扩缩指标、冷却时间、最大实例数)

9. 名词速查表

| 名词 | 英文 | 解释 | | ---------------- | --------------------- | ---------------------------------------- | ------------------------------ | | 负载均衡器 | Load Balancer | 将流量分发到多个后端服务器的设备或软件 | | 四层负载均衡 | L4 Load Balancing | 基于传输层(TCP/UDP)的负载均衡 | | 七层负载均衡 | L7 Load Balancing | 基于应用层(HTTP/HTTPS)的负载均衡 | | 健康检查 | Health Check | 定期检查后端服务器的健康状态的机制 | | 会话保持 | Session Persistence | 确保同一用户的请求始终路由到同一台服务器 | | 粘性会话 | Sticky Session | 另一种称呼,同Session Persistence | | 蓝绿部署 | Blue-Green Deployment | 两套环境切换的零停机发布策略 | | 金丝雀发布 | Canary Release | 小流量先行验证的灰度发布策略 | | 自动扩缩容 | Auto Scaling | 根据负载自动增加或减少服务器数量 | | 水平扩展 | Horizontal Scaling | 增加服务器数量来提升处理能力 | | 垂直扩展 | Vertical Scaling | 提升单机配置(CPU、内存)来提升处理能力 | | 多区域 | Multi-Region | 在多个地理区域部署服务 | | 多活 | Active-Active | 多个区域同时对外提供服务 | | 主备 | Active-Standby | 只有一个区域提供服务,其他待命 | | 数据同步 | Data Replication | 跨区域的数据复制机制 | | RTO | RTO | 恢复时间目标 | 系统故障后需要在多长时间内恢复 | | RPO | RPO | 恢复点目标 | 系统故障后可以接受的数据丢失量 |