---
title: 负载均衡器的工作原理
taxonomy:
    category: docs
---

本节将详细介绍负载均衡器的工作原理，相信读者在阅读后能够对这一概念有更深入的理解。

### 真实世界中 TCP 连接数和 QPS 的比例

在实际环境中，QPS（每秒查询率）通常低于保持 TCP 连接的客户端数量。也就是说，打开应用的用户并非每秒都会发起一次 API 请求，平均每隔几秒才会有一次操作。假设这个时间为 4 秒一次，那么：如果有 20 万个客户端在线，每个客户端设备平均每 4 秒发送一个 HTTPS 请求，QPS 为`200000 ÷ 4 = 50000`。

### 单台 Nginx 反向代理的性能极限

Nginx 不仅需要建立 TCP 连接，还需要将 TCP 连接中发送过来的数据包与某个进程/线程进行匹配，同时还需要对 HTTP 协议的信息进行解析、识别、转换、添加。因此，Nginx 也有其 QPS 上限：

在 2015 年主流的服务器 CPU 上，Nginx 官方在进行了极限优化的情况下进行了反向代理性能测试。在完整执行“建立 TCP 连接-发送 HTTPS 请求-断开 TCP 连接”这样一整个“网络事务”的情况下，最高性能为 [60000 QPS（SSL TPS RSA 2048bit）](https://www.nginx.com/resources/datasheets/nginx-plus-sizing-guide/)。

假设我们使用最新的服务器硬件，当虚拟机 CPU 达到 32 vCore 的时候，未经优化的单机 Nginx 性能就已经达到极限，能承受大约 1 万 HTTPS QPS，对应的连接用户就是 4 万，这就是 Nginx 在单台 x86 物理服务器上的极限。

我们假设单台 Kong 应用网关的极限为 1 万 QPS，于是我们就需要五台 Kong。那么这五台 Kong 前面的 TCP 负载均衡器为何能够扛住呢？因为 TCP 负载均衡器要做的事情比 Kong 少非常多：它只需要在 IP 层做少量的工作即可。

### 使用负载均衡器拆分 TCP 单点

TCP 协议是一种“可靠地传输信息”的方法，它不仅有三次握手四次挥手等复杂的控制流程，还会对每一个报文段进行排序、确认、重发等操作来保证最终数据的完整和正确。因此，TCP 本身就是一种需要很多资源处理的`单点`。现在我们开始拆分这个单点。

### TCP 负载均衡器的工作过程

我们假设一个含有负载均衡器的系统：客户端 IP 为 `123.123.123.123`，负载均衡器的 IP 为 `110.242.68.3`（公网）和 `10.0.0.100`（私网），五台 Kong 服务器的 IP 为 `10.0.0.1` ~ `10.0.0.5`，那么这个系统的架构就如图 5-8 所示。

![](https://qn.lvwenhan.com/2023-01-06-16730021122858.jpg)
<center>图 5-8 使用 TCP 负载均衡器时的架构图</center>

负载均衡器的工作过程如下：

#### 1. 接收数据（左侧）

负载均衡器接收客户端数据包（报文）的过程如下：

1. 负载均衡器收到了一个 IP 报文，其源地址为 123.123.123.123，目的地址为 110.242.68.3。
2. IP 报文内包裹着一个 TCP 报文，具体信息如下：源端口为 52387，目的端口为 443。
3. 需要注意的是，负载均衡器仅接收了一个 IP 报文，并未与客户端进行三次握手，也未与客户端建立“TCP 连接”。

#### 2. 发送数据给上游服务器（右侧）

在接收到客户端的 IP 报文后，负载均衡器会寻找一台上游服务器，准备将数据发送过去：

1. 内部 TCP 报文首部：源端口为 45234，目的端口为 443。
2. TCP 报文外层包裹的 IP 首部：源地址为 10.0.0.100，目的地址为 10.0.0.1。
3. 负载均衡器将包裹着 TCP 数据包的 IP 报文发送出去。

#### 3. 建立映射关系并进行数据转发

负载均衡器会在内存中创建两个五元组：

左侧五元组

1. 左侧源地址 123.123.123.123
2. 左侧目的地址 110.242.68.3
3. 左侧源端口 52387
4. 左侧目的端口 443
5. 协议 TCP

右侧五元组

1. 右侧源地址 10.0.0.100
2. 右侧目的地址 10.0.0.1
3. 右侧源端口 45234
4. 右侧目的端口 443
5. 协议 TCP

然后，负载均衡器会关联这两个五元组：对两侧发来的数据包（报文）进行拆包和修改（两个地址+两个端口），并从另一侧发送出去。

对于阅读过笔者《软件工程师需要了解的网络知识》系列文章的读者来说，应该能够一眼看出，这就是网关的工作模式，你家几百块的路由器主要执行的就是这个任务。

### 为什么负载均衡器性能开销比 Kong 低

通过前面的内容我们可以发现，负载均衡器/网关只需要执行两个主要任务：建立五元组并关联，以及修改数据包的地址和端口并将其发送出去。这个过程在网络领域被称为 NAT（网络地址转换）。

由于这个操作相对简单，大部分工作可以通过专用硬件来完成。例如，可以开发专门用于存储和关联五元组的芯片，以及专门的 NPU（网络数据包处理器）来进行快速的数据修改。正因为可以使用低性能的专用硬件来实现，家用路由器才能以低于 300 元的终端售价实现超过 1Gbit/S 的 NAT 性能。

### Kong 网关需要建立“真·TCP连接”

与负载均衡器只需执行两个任务相比，Kong 网关需要真正地与客户端建立 TCP 连接。具体来说，它需要进行以下操作：

1. 进行三次握手以建立 TCP 连接；
2. 对数据包进行排序、校验，并在收到心跳包时进行回复；
3. 将该 TCP 连接与一个进程/线程绑定：
   - 在收到数据后，找到相应的进程/线程并将数据发送给它；
   - 等待进程/线程回复后，再找到对应的 TCP 连接并将数据发送出去。

这一系列操作流程较长，且经常需要进行配置修改。如果设计专用硬件来实现，可能会过于复杂，并且收益可能低于投入。因此，使用通用 CPU 加软件的解决方案更加合适。

#### 四层和七层负载均衡（L4/L7）

在商业负载均衡公司中，应用网关也被称为七层负载均衡，因为它工作在 OSI 七层网络模型的第七层。而我们讨论的负载均衡工作在 IP 层的称为四层负载均衡，工作在 OSI 七层网络模型的第四层。读者以后看到 L4、L7 这两个词时，应该能一眼看穿它们了，其实一点都不神秘。

### 五万 QPS 下静山平台的架构图

在一个 TCP 负载均衡器下挂载五个安装了 Kong 应用网关的 6 vCore 虚拟机，再下挂 125 台 8 vCore 的 PHP 虚拟机——静山平台的五万 QPS 终于被系统给支撑住了。此时静山平台的架构如图 5-9 所示。

![](/media/16895803968600.png)
<center>图 5-9 引入 TCP 负载均衡器之后的静山平台架构图</center>
