Computer NetworkNotes

第 20 章:负载均衡

zjc 于 2026-01-20 发布

这是《计算机网络 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 负载均衡把流量分发到多个后端实例,是横向扩展、灰度发布和高可用的基础。它不只是“轮询选一台机器”,还涉及健康检查、会话保持、连接 draining、四层与七层能力、过载保护和故障切换。

20.1 为什么需要负载均衡

单机瓶颈:

流量增长
  -> CPU / 内存 / 连接数不足
     -> 无法无限纵向扩容
        -> 多实例水平扩展
           -> 需要统一入口分发

负载均衡提供:

  1. 流量分发;
  2. 健康检查;
  3. 故障摘除;
  4. 平滑发布;
  5. TLS 终止;
  6. 限流防护;
  7. 观测入口;
  8. 多可用区容灾。

20.2 四层与七层

类型 工作层 能力 典型实现
L4 传输层 按 IP 和端口转发,性能高 LVS、云 NLB、IPVS
L7 应用层 按 HTTP 路径、Header、Cookie 路由 Nginx、HAProxy、Envoy、云 ALB

选择:

  1. TCP/UDP 私有协议、超高性能转发:L4;
  2. HTTP 路由、TLS、重写、限流、灰度:L7;
  3. 大型系统常组合使用:L4 承接入口,L7 做业务路由。

20.3 常见算法

算法 特点
轮询 依次分发,简单
加权轮询 按机器规格分配
最少连接 优先给当前连接少的节点
加权最少连接 兼顾规格和负载
源 IP Hash 同源尽量稳定
一致性 Hash 节点变化时减少映射变化
随机 实现简单,异常时可能不均
响应时间 依赖探测质量

长连接场景不能只看请求速率。如果每次连接持续数小时,轮询建连数均衡不代表当前在线连接或消息量均衡。

20.4 健康检查

健康检查类型:

  1. TCP 端口检查;
  2. HTTP GET;
  3. 自定义健康接口;
  4. gRPC Health Check;
  5. 执行外部脚本;
  6. 管理面进程检查。

Nginx 主动检查:

upstream app {
    server 10.0.1.10:8080;
    server 10.0.1.11:8080;
    health_check interval=5s fails=3 passes=2;
}

健康接口设计:

/health/live:进程存活
/health/ready:可以承接流量

readiness 应检查:

  1. 应用已启动;
  2. 依赖可用性是否满足承接条件;
  3. 配置加载完成;
  4. 预热完成;
  5. 当前过载状态。

注意:不要让非关键依赖导致整个服务被摘除。如果报表缓存不可用但核心下单可用,应分级降级。

20.5 会话保持

方式:

  1. Source IP Hash;
  2. Cookie 插入;
  3. 应用 Session ID 粘滞;
  4. 服务端外部会话存储;
  5. 客户端令牌。

建议优先无状态设计。需要粘滞的场景要考虑:

  1. 节点故障后的会话迁移;
  2. 灰度发布期间兼容;
  3. 长连接迁移成本;
  4. 数据局部性;
  5. 负载倾斜。

20.6 连接与请求 draining

发布时不能直接把实例从集群删除并杀死进程。

正确流程:

1. 标记实例为 draining
2. 从新流量分配中移除
3. 保留既有连接处理
4. 主动通知客户端重连或等待连接结束
5. 观察连接数下降
6. 达到超时后优雅关闭
7. 停止进程并发布

注意:

  1. 长连接需要更长的 drain 时间;
  2. 服务端可发送 GoAway 或关闭帧;
  3. 客户端要有重连机制;
  4. 任务实例要处理任务租约;
  5. 数据库连接要等待事务结束;
  6. 强杀会造成请求失败和数据不一致。

20.7 高可用架构

入口层:

DNS / Anycast
  -> L4 LB 多可用区
     -> L7 Gateway 多副本
        -> Service Pods 多副本

关键设计:

  1. LB 自身多节点;
  2. 配置热更新;
  3. 后端多可用区;
  4. 健康检查不同步误判;
  5. 防止 LB 单点;
  6. 管理面故障不影响数据面;
  7. 后端容量和 LB 容量同时规划;
  8. 入口带宽可扩展。

20.8 HAProxy 示例

frontend api_frontend
    bind *:443 ssl crt /etc/haproxy/tls/api.pem
    default_backend api_backend

backend api_backend
    balance leastconn
    option httpchk GET /health/ready
    http-check expect status 200
    server app1 10.0.1.10:8080 check inter 5s fall 3 rise 2
    server app2 10.0.1.11:8080 check inter 5s fall 3 rise 2

常用观测:

  1. 当前连接数;
  2. 每秒新建连接;
  3. 每秒请求;
  4. 后端延迟;
  5. 5xx 比例;
  6. 健康状态;
  7. 队列长度;
  8. 重试次数。

20.9 常见故障

后端全部不健康

现象:503。检查健康接口、后端进程、安全组、探针路径、Host 头和协议。

流量倾斜

检查算法、连接时长、Hash key、单机容量、健康检查和长连接分布。

偶发 502

排查后端主动 RST、连接队列溢出、网关重试、后端重启和空闲超时。

偶发 504

查看后端处理耗时、网关读超时、慢依赖和 GC 停顿。

客户端本地缓存旧后端

服务发现、DNS、连接池未刷新都可能导致。

本章小结

负载均衡通过算法、健康检查和流量摘除实现多实例水平扩展。L4 性能高,L7 语义强,二者常组合使用。生产重点是 readiness 分级、优雅 draining、长连接治理、LB 自身高可用和容量监控。502、503、504 需要结合 LB、后端和客户端三方证据定位。

思考题

  1. L4 和 L7 负载均衡分别适合什么场景?
  2. 轮询在长连接场景有什么问题?
  3. liveness 和 readiness 有什么区别?
  4. 设计长连接服务的 draining 流程。
  5. 为一个多可用区 API 服务设计 LB 和健康检查方案。