本节将深入剖析 LVS 软件的技术原理,探索其设计思想,并追踪数据包的修改和传递路径。
1998 年,章文嵩正在读博士二年级,他发现 Cisco 的硬件负载均衡器售价昂贵,于是利用了两周的课余时间,创建并开源了 LVS(当时称为 IPVS)。如今,LVS 技术所创造的商业价值已无法估量,互联网上的绝大部分数据包都由 LVS 或承袭 LVS 思想的软件处理。
2004 年,LVS(IPVS)被纳入了 kernel 2.4,从此之后,所有 Linux 系统都具备了变身为负载均衡器的能力。
LVS 的基本原理可以用一句话概括:通过修改 MAC 层、IP 层、TCP 层的数据包,实现了一部分交换机和网关的功能,从而指挥流量到达真正的服务器上。
LVS 有三种常用模式:
我们以最能体现 LVS 思想的 DR 模式为例,展示 LVS 的基本原理。
LVS 在 DR 模式时,运行架构如图 6-4 所示。在 DR 模式下,LVS 只负责修改数据包,不充当网关的角色。因此,我们仍然需要一个网关来执行公网 IP 和私网 IP 之间的 NAT 转换。假设客户端 IP 为 123.123.123.123,它向 110.242.68.3 的 80 端口发起了一个 HTTP 请求。
当网关接收到一个发送给 110.242.68.3 的数据包时,发现协议为 TCP,目标端口为 80。通过查询自己的 NAT 表,网关发现内部 IP 为 10.0.0.100(即虚拟 IP),内部端口为 80。于是,网关向局域网发送了一个 IP 包。由于端口和协议保持不变,本次网络请求中的关键数据有四个:源 IP 地址、目的 IP 地址、源 MAC 地址和目的 MAC 地址。
通过前面的推演过程,大家可以看出 DR 模式的特点:
在生产环境部署中,由于 LVS 集群是所有流量的入口,所以其可用性需要非常高,一般不会只部署在一个机房里,因此最常用的是 NAT 模式:双向流量都经过 LVS 集群,这样可以实现多地多中心的跨公网多活。
通过上述过程,你应该能理解 LVS 的运行原理:它通过在 LVS 和上游服务器上配置虚拟 IP,以修改数据包后再发送为手段,在标准以太网模型下构建了一个可行的负载均衡系统。它不像交换机那样完全不修改数据包,也不像网关那样维持一个对应关系并修改很多东西,它修改了数据包,但不多,因此可以实现非常高的性能。
LVS 的数据处理组件 IPVS 运行在内核态,避免了用户态 IPVS 进程和内核态 Linux 网络进程之间频繁的状态切换导致的内存读写开销,在高并发下这种设计可以带来非常高的性能收益。由于有内核态支持,LVS 比 HAProxy 和 Nginx 的单机性能都要强很多。
2014 年,eBPF 首次被引入了 Kernel 3.18,它的出现让新时代的 LVS 不再需要合并进内核才能使用内核态,让普通软件也能直接进入内核态,为高性能软件打开了一扇大门。eBPF 是目前最热门的内核相关技术,它为我们自行开发属于自己的内核态软件提供了可能——除了合并进内核之外,Kernel 的用户有了自己“热加载”内核代码的能力。
LVS 是运行在标准以太网模型下的负载均衡软件,配合 Keepalived 可以实现高可用。而 OSPF/ECMP 协议是专业的多链路路由协议,可以实现不丢包的多活。
OSPF:开放式最短路径优先协议,一种基于链路状态的内部网关协议。每个 OSPF 路由器都包含了整个网络的拓扑,并计算通过网络的最短路径。OSPF 会通过多播的方式自动对外传播检测到的网络变化。
ECMP:等价多路径协议。当存在多条不同的链路到达同一目的地址时,利用 ECMP 可以同时使用多条链路,不仅增加了传输带宽,还可以无时延、无丢包地备份失效链路的数据传输。如果使用传统的路由算法,只能利用其中的一条链路进行数据的传输,还存在丢包的可能性。
LVS 是网关型负载均衡继续拆单点的结果:LVS 将网关这个单点拆分成了“重定向”和“转发”,自己只承担数据包重定向工作,将转发留给基础网以太网来解决,在单机上实现了非常高的系统容量。在最新的 x86 服务器上,单个 LVS 即使在开销更大的 NAT 模式下也可以实现大约 20G 的 TCP 带宽—— 用 dperf 测试 LVS 的性能数据。
📙 高并发的哲学原理 《Philosophical Principles of High Concurrency》
Copyright © 2023 吕文翰