负载均衡(Load Balancing)

什么是负载均衡

负载均衡本质上是一个反向代理(Reverse Proxy)*或*数据包转发器。它位于客户端(Client)和后端服务集群(Upstream Servers)之间,通过向外暴露一个虚拟IP(VIP),屏蔽了后端具体的网络拓扑结构。

为什么我们需要负载均衡?

在计算机系统中,使用负载均衡主要有三个巨大的好处:

  1. 高可用性(High Availability / Reliability): 如果有服务器坏了(宕机),负载均衡器会立刻发现,并停止向它发送请求,转而分发给其他健康的服务器。这样用户就感觉不到服务中断。
  2. 高性能(Performance): 通过将流量分摊,避免单一服务器过载,从而保证网页打开的速度和响应时间。
  3. 可扩展性(Scalability): 如果业务突然增长(比如双11大促),你可以随时增加几台新服务器进来,负载均衡器会自动开始给它们分配任务,非常灵活。
image-20251217201102150

它是怎么分配任务的?(常见算法)

负载均衡器并不是“瞎”分配的,它有一套策略(算法)来决定把请求给谁。最常见的有这几种:

  • 轮询(Round Robin): 最简单的策略。按顺序一个一个来:请求1给服务器A,请求2给服务器B,请求3给服务器C,请求4又回到服务器A。
  • 最小连接数(Least Connections): 比较智能。它会看谁现在手头的活儿最少(连接数最少),就把新任务给谁。适合某些任务处理时间长短不一的场景。
  • 源地址哈希(IP Hash): 为了保证“从一而终”。它保证来自同一个 IP 地址的用户,总是被分配到同一台服务器上。这在需要保持登录状态(Session)的场景中很有用。

OSI 模型(Open Systems Interconnection Model)

互联网数据传输原理 |OSI七层网络参考模型_哔哩哔哩_bilibili

7. 应用层 (Application Layer)

  • 作用: 直接与用户打交道,为应用程序提供网络服务接口。
  • 关键点: 这是用户“看得到”的一层。
  • 常见协议: HTTP (网页), FTP (文件), SMTP (邮件), DNS (域名)。
  • 数据单元: Data (数据)

6. 表示层 (Presentation Layer)

  • 作用: 数据的“翻译官”。负责数据的格式化、加密/解密、压缩/解压缩。
  • 关键点: 确保一个系统的应用层发送的数据能被另一个系统的应用层读取。比如把 JSON 对象转成二进制,或者处理 SSL/TLS 加密。
  • 常见格式: JPEG, ASCII, EBCDIC, SSL/TLS。

5. 会话层 (Session Layer)

  • 作用: 建立、管理和终止应用程序之间的“会话”(Session)。
  • 关键点: 它负责断点续传、同步点。比如你从网盘下载文件,断网了,下次能接着下,就是会话层的功劳。
  • 常见协议: RPC, SQL。

4. 传输层 (Transport Layer) —— (关键层级)

  • 作用: 负责端到端(End-to-End)的数据传输,区分具体的应用程序(通过端口号)。
  • 关键点: 负载均衡中的“四层负载”就在这里。它决定了数据是“可靠传输”(TCP)还是“快速传输”(UDP)。
  • 核心设备/概念: 端口 (Port), 负载均衡器 (L4)。
  • 常见协议: TCP (可靠, 三次握手), UDP (快速, 直播/游戏)。
  • 数据单元: Segment (段)

3. 网络层 (Network Layer) —— (关键层级)

  • 作用: 负责地址寻址和路由选择(Routing)。决定数据包如何从从源地址到达目的地址(跨网络)。
  • 关键点: IP 地址在这里起作用。路由器(Router)工作在这一层。
  • 常见协议: IP, ICMP (Ping), OSPF, BGP。
  • 数据单元: Packet (包)
  • 作用: 负责节点到节点(Node-to-Node)的传输,处理物理寻址。
  • 关键点: MAC 地址在这里起作用。交换机(Switch)通常工作在这一层。它负责在同一局域网内把数据帧发给对的人。
  • 常见协议: Ethernet (以太网), VLAN, Wi-Fi (802.11)。
  • 数据单元: Frame (帧)

1. 物理层 (Physical Layer)

  • 作用: 传输比特流(0 和 1)。
  • 关键点: 真正的物理介质。把数字信号转换成电信号、光信号或无线电波。
  • 核心设备: 网线, 光纤, 集线器 (Hub), 中继器。
  • 数据单元: Bit (比特)

TCP/IP 协议栈

1. 为什么叫 TCP/IP?

虽然名字里只有 TCP 和 IP,但它其实是一个协议族(Protocol Suite),包含了几十个协议。 之所以用这两个命名,是因为它们最重要:

  • IP (Internet Protocol): 负责把数据包送到目的地(解决“路怎么走”)。
  • TCP (Transmission Control Protocol): 负责把数据可靠地传输(解决“东西别丢了”)。

2. TCP/IP 的四层模型(与 OSI 的映射)

TCP/IP 更加务实,它将 OSI 的 7 层模型压缩为了 4 层

我们由上至下来看:

第一层:应用层 (Application Layer)

  • 对应 OSI: 应用层 + 表示层 + 会话层
  • 功能: 处理特定的应用程序细节。
  • 常见协议:
    • HTTP/HTTPS: 浏览网页。
    • SSH: 远程登录服务器。
    • DNS: 域名解析(把 google.com 变成 IP 地址)。
    • FTP: 文件传输。

第二层:传输层 (Transport Layer)

  • 对应 OSI: 传输层
  • 功能: 提供端到端(Host-to-Host)的通信服务。它只关心两台主机上的进程(通过端口号区分),而不关心中间经过了多少路由器。
  • 两大主角:
    • TCP: 可靠、面向连接(打电话)。
    • UDP: 不可靠、无连接(大喇叭广播)。

第三层:网络层 (Internet Layer)

  • 对应 OSI: 网络层
  • 功能: 处理数据包在网络中的路由选择。这是互联网的核心
  • 核心协议:
    • IP (IPv4/IPv6): 核心载体。
    • ICMP: 比如 ping 命令就在这里工作,用来报错或探测。
    • ARP: 地址解析协议(知道 IP 找 MAC 地址)。

第四层:网络接口层 (Network Interface Layer)

  • 对应 OSI: 数据链路层 + 物理层
  • 功能: 处理与物理硬件的交互。TCP/IP 标准对这一层并没有严格定义,只要能传 IP 数据包就行。
  • 常见技术: 以太网 (Ethernet)、Wi-Fi。

常见的负载均衡分类

你可能会听到“四层负载”和“七层负载”这样的术语,它们的区别在于“指挥”的层级不同:

类型 对应层级 (OSI模型) 特点 典型代表
四层负载均衡 (L4) 传输层 (TCP/UDP) 速度快。只看 IP 和端口号,不看内容,直接转发数据包。 LVS, F5 (硬件)
七层负载均衡 (L7) 应用层 (HTTP/HTTPS) 更智能。它能看懂 URL、Cookie、头部信息。比如把 /image 的请求分给图片服务器,把 /api 的请求分给应用服务器。 Nginx, HAProxy, AWS ALB

正向代理和反向代理

正向代理 (Forward Proxy) —— 代表客户端

这是大家通常说的“挂代理”或“梯子”。

  • 场景: 你(客户端)想访问 Google,但直接访问不了。
  • 做法: 你连上一个代理服务器,对它说:“帮我访问 Google”。代理服务器去访问 Google,把结果拿回来给你。
  • 特点: Google 不知道是你访问的,它只看到了代理服务器。
  • 作用: 隐藏客户端身份,突破访问限制。

反向代理 (Reverse Proxy) —— 代表服务端

这是互联网公司部署在自家门口的“门卫”。

  • 场景: 你(客户端)访问 www.baidu.com
  • 做法: 你的请求其实并没有直接到达百度的核心数据库或应用服务器,而是先到达了百度的反向代理服务器。这个代理服务器决定把你的请求转给内部的哪台机器处理,处理完后再把结果给你。
  • 特点: 你(客户端)不知道具体是哪台内部服务器为你服务的,你只看到了反向代理。
  • 作用: 隐藏服务端身份,保护内部网络。

常见问题

如何解决多个服务器session一致性的问题

这是一个非常经典的分布式系统架构问题。

在单体架构(一台服务器)中,Session 保存在服务器的内存里,这没问题。 但在集群环境(多台服务器)下,默认情况是这样的:

  1. 用户在 服务器 A 登录,Session 存在 A 的内存里。
  2. 下一次请求,负载均衡器把用户分发到了 服务器 B
  3. 服务器 B 的内存里没有这个 Session,于是判断用户“未登录”,强制踢下线。

为了解决这个问题,业界主要有四种成熟的方案,我会按推荐程度从低到高为您介绍:

1. 方案一:会话保持 (Sticky Sessions / Session Affinity)

原理: 让负载均衡器“记住”用户。 如果不改变代码,这是最简单的改法。我们在负载均衡器(如 Nginx)上配置策略,保证同一个 IP 的请求永远只发给同一台服务器

  • 实现方式: Nginx 的 ip_hash 策略。
  • 优点:
    • 简单,不需要修改任何应用程序代码。
    • 不需要引入额外的存储组件。
  • 缺点:
    • 故障丢失: 如果这台服务器宕机,上面所有用户的 Session 全部丢失。
    • 负载不均: 如果某个公司几千人都用同一个公网 IP 出口,这些请求会全部压在同一台服务器上,导致负载均衡失效。

2. 方案二:Session 复制 (Session Replication)

原理: 让服务器之间“互通有无”。 当服务器 A 产生了一个 Session,它通过网络广播把这个 Session 同步给服务器 B、C、D。

  • 实现方式: Tomcat 集群自带的 Session 复制功能。
  • 优点:
    • 服务器宕机不会丢失 Session(因为其他机器也有)。
  • 缺点(致命):
    • 性能极差: 每次存取 Session 都要广播,网络风暴严重。
    • 扩展性差: 随着服务器数量增加,同步数据的成本呈指数级上升。通常不建议在生产环境使用。

3. 方案三:集中式 Session 存储 (Centralized Session Storage) —— 【最推荐】

原理: Session 也不存 A,也不存 B,而是存到一个公共的“保险柜”里。 所有的服务器在处理请求时,都去这个公共的地方读写 Session。

  • 实现方式: 使用 Redis 或 Memcached 作为 Session 仓库。
    • Spring Boot 项目中只需引入 spring-session-data-redis 依赖,几行配置就能搞定。
  • 优点:
    • 无状态化: 应用服务器变得“无状态”(Stateless),可以随意增加或减少服务器,不影响用户体验。
    • 高可用: 某台应用服务器挂了,用户被切到另一台,Session 依然在 Redis 里,用户无感知。
    • 速度快: Redis 是基于内存的,读写速度极快。
  • 缺点:
    • 引入了新的组件(Redis),需要保证 Redis 的高可用(如使用 Redis Cluster)。

4. 方案四:客户端存储 (Token / JWT) —— 【现代架构主流】

原理: 服务器根本不存 Session。 服务器生成一个加密的令牌(Token),交给客户端(浏览器/App)自己保存。客户端每次请求都带着这个令牌,服务器解密验证身份。

  • 实现方式: JWT (JSON Web Token)
  • 优点:
    • 极致的服务器无状态: 服务器不需要查数据库,也不需要查 Redis,只要通过 CPU 计算验签即可。
    • 适合微服务: 一个 Token 可以在多个不同的微服务之间通用。
  • 缺点:
    • 不可撤销: 一旦 Token 发出去,在过期前都有效。如果用户想改密码或被封号,服务器很难强制让 Token 立刻失效(除非引入黑名单机制,但这又变回了方案三)。
    • 带宽占用: Token 通常比 Session ID 长,每次请求都要带,稍微增加一点流量。

如何保证负载均衡器的高可用性

如果我们只部署了一个负载均衡器(比如一台 Nginx),虽然它帮后端服务器分担了压力,但它自己就成了整个系统的单点故障(SPOF - Single Point of Failure)。一旦这台 Nginx 宕机,整个网站就彻底瘫痪了,后端有再多服务器也没用。

为了解决这个问题,业界通用的标准方案是:高可用架构(High Availability Architecture),核心思想是“冗余”“自动故障转移(Failover)”

最主流的实现方式有以下几种:

1. 主备模式 (Active-Passive) —— 最经典方案

这是最简单、最常用,也是中小企业首选的方案。通常使用 Keepalived 软件配合 VRRP 协议 来实现。

架构设计:

  • 准备两台 LB: 一台作为主节点(Master),一台作为备节点(Backup)
  • VIP(虚拟 IP): 两台机器对外只暴露一个虚拟 IP (Virtual IP)。正常情况下,这个 VIP 绑定在主节点上。用户只访问这个 VIP。
  • 心跳检测: 备节点会每隔几秒向主节点发送“心跳包”确认它还活着。

工作流程:

  1. 正常状态: 所有的流量都流向拥有 VIP 的主节点,备节点闲置待命。
  2. 故障发生: 主节点挂了(比如断电、进程崩溃),备节点收不到心跳包。
  3. IP 漂移 (IP Failover): 备节点立刻通过 VRRP 协议把 VIP“抢”过来,绑定到自己身上。
  4. 恢复: 对用户来说,只是网络卡顿了一瞬间,请求马上就能被备节点处理,服务未中断。
  • 优点: 简单稳定,配置方便。
  • 缺点: 资源有一半是浪费的(备节点平时不干活)。

2. 双主模式 (Active-Active) —— 高性能方案

如果你觉得有一台机器闲置太浪费,可以使用双主模式。

架构设计:

  • 准备两台 LB: 这里的两台都是 Master。
  • 两个 VIP: 配置两个不同的虚拟 IP(VIP_A 和 VIP_B)。
  • DNS 轮询: 在域名解析(DNS)层面,将域名同时解析到这两个 VIP 上。

工作流程:

  • 用户 A 解析到了 VIP_A,流量走了 LB 1。
  • 用户 B 解析到了 VIP_B,流量走了 LB 2。
  • 互为备份: LB 1 是 LB 2 的备用,LB 2 也是 LB 1 的备用。
  • 故障发生: 如果 LB 1 挂了,Keepalived 会把 VIP_A 漂移到 LB 2 上。此时 LB 2 身上同时挂着 VIP_A 和 VIP_B,独自承担所有流量。
  • 优点: 资源利用率最大化,两台机器都在工作。
  • 缺点: 架构稍复杂,需要设计好容量,确保一台机器能扛住两倍的流量(万一另一台挂了)。

3. 全局负载均衡 (GSLB) —— 异地多活

如果整个机房(数据中心)都停电了或者光缆被挖断了,上面的方法都得死。这时候需要更高层级的DNS 负载均衡

  • 原理: 在 DNS 服务器上配置策略。
  • 实现:
    • 北京的用户解析到北京机房的负载均衡器 IP。
    • 上海的用户解析到上海机房的负载均衡器 IP。
  • 高可用: 如果北京机房挂了,DNS 服务器检测到后,会自动把北京用户的流量引导到上海机房。

Nginx

Nginx入门必须懂3大功能配置 - Web服务器/反向代理/负载均衡_哔哩哔哩_bilibili

Caddy

全自动HTTPS加密,开箱即用,Caddy基础入门,反向代理,负载均衡,网站托管全流程_哔哩哔哩_bilibili

参考资料

什么是负载均衡?不就是加台服务器么?_哔哩哔哩_bilibili