图文详解 LVS 工作原理

一、负载均衡由来

在业务初期,我们一般会先使用单台服务器对外提供服务。随着业务流量越来越大,单台服务器无论如何优化,无论采用多好的硬件,总会有性能天花板,当单服务器的性能无法满足业务需求时,就需要把多台服务器组成集群系统提高整体的处理性能。不过我们要使用统一的入口方式对外提供服务,所以需要一个 流量调度器 通过均衡的算法,将用户大量的请求均衡地分发到后端集群不同的服务器上。这就是我们后边要说的 负载均衡。

使用负载均衡带来的好处

二、负载均衡类型

广义上的负载均衡器大概可以分为 3 类,包括:DNS 方式实现负载均衡、硬件负载均衡、软件负载均衡。

2.1 DNS 实现负载均衡

DNS 实现负载均衡是最基础简单的方式。一个域名通过 DNS 解析到多个 IP,每个 IP 对应不同的服务器实例,这样就完成了流量的调度,虽然没有使用常规的负载均衡器,但也的确完成了简单负载均衡的功能。

img

通过 DNS 实现负载均衡的方式,最大的优点就是实现简单,成本低,无需自己开发或维护负载均衡设备,不过存在一些缺点:

实际上生产环境中很少使用这种方式来实现负载均衡,毕竟缺点很明显。文中之所以描述 DNS 负载均衡方式,是为了能够更清楚地解释负载均衡的概念。一些大公司一般也会利用 DNS 来实现地理级别的负载均衡,实现就近访问,提高访问速度,这种方式一般是入口流量的基础负载均衡,下层会有更专业的负载均衡设备实现的负载架构。

2.2 硬件负载均衡

硬件负载均衡是通过专门的硬件设备来实现负载均衡功能,类似于交换机、路由器,是一个负载均衡专用的网络设备。目前业界典型的硬件负载均衡设备有两款:F5 和 A10。这类设备性能强劲、功能强大,但价格非常昂贵,一般只有 “土豪” 公司才会使用此类设备,普通业务量级的公司一般负担不起,二是业务量没那么大,用这些设备也是浪费。

硬件负载均衡的优点:

硬件负载均衡的缺点:

注:至今没有用过硬件负载均衡,不过有幸曾经与 F5 有过一面之缘。

2.3 软件负载均衡

软件负载均衡,可以在普通的服务器上运行负载均衡软件,实现负载均衡功能。目前常见的有 Nginx、HAproxy、LVS。其中的区别:

软件负载均衡的优点
- 简单:无论是部署还是维护都比较简单。
- 便宜:买个 Linux 服务器,装上软件即可。
- 灵活:4 层和 7 层负载均衡可以根据业务进行选择;也可以根据业务特点,比较方便进行扩展和定制功能。

三、开源负载均衡器 LVS

软件负载均衡主要包括:Nginx、HAproxy 和 LVS。其实三款负载均衡软件都十分常用。四层负载均衡基本上都会使用 LVS,据了解如 BAT 等大厂都是 LVS 重度使用者,就是因为 LVS 非常出色的性能,能为公司节省很大成本。

了解到很多大公司使用的 LVS 都是定制版的,做过很多性能方面的优化,比开源版本性能会高出很多。目前只有淘宝开源过优化过的 alibaba/LVS,支持 FNAT 模式,但是也很久没有更新过了。另外爱奇艺去年开源出了 DPDK 版本的 LVS,名叫 DPVS,性能非常强悍。

目前较为熟悉的负载均衡软件是 LVS,且大部分中小型公司使用开源的 LVS 足够满足业务需求。

3.1 netfilter基本原理
LVS 是基于 Linux 内核中 netfilter 框架实现的负载均衡系统,所以要学习 LVS 之前必须要先简单了解 netfilter 基本工作原理。netfilter 其实很复杂也很重要,平时我们说的 Linux 防火墙就是 netfilter,不过我们平时操作的都是 iptables,iptables 只是用户空间编写和传递规则的工具而已,真正工作的是 netfilter。通过下图可以简单了解下 netfilter 的工作机制:

img

netfilter 是内核态的 Linux 防火墙机制,作为一个通用、抽象的框架,提供了一整套的 hook 函数管理机制,提供诸如数据包过滤、网络地址转换、基于协议类型的连接跟踪的功能。

通俗点讲,就是 netfilter 提供一种机制,可以在数据包流经过程中,根据规则设置若干个关卡(hook 函数)来执行相关的操作。netfilter 总共设置了 5 个点,包括:PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING

当一个数据包进入网卡,经过链路层之后进入网络层就会到达 PREROUTING,接着根据目标 IP 地址进行路由查找,如果目标 IP 是本机,数据包继续传递到 INPUT 上,经过协议栈后根据端口将数据送到相应的应用程序;应用程序处理请求后将响应数据包发送到 OUTPUT 上,最终通过 POSTROUTING 后发送出网卡。如果目标 IP 不是本机,而且服务器开启了 forward 参数,就会将数据包递送给 FORWARD 上,最后通过 POSTROUTING 后发送出网卡。

3.2 LVS基本原理

LVS 是基于 netfilter 框架,主要工作于 INPUT 链上,在 INPUT 上注册 ip_vs_in HOOK 函数,进行 IPVS 主流程,大概原理如图所示:

img

开源 LVS 版本有 3 种工作模式,每种模式工作原理截然不同,说各种模式都有自己的优缺点,分别适合不同的应用场景,不过最终本质的功能都是能实现均衡的流量调度和良好的扩展性。主要包括以下三种模式:

另外必须要说的模式是 FullNAT,这个模式在开源版本中是模式没有的,代码 没有合并进入内核主线版本,后面会有专门章节详细介绍 FullNAT 模式。下边分别就 DR、NAT、Tunnel 模式分别详细介绍原理。

3.3 DR 模式实现原理

LVS 基本原理图(上图)中描述的比较简单,表述的是比较通用流程。下边会针对 DR 模式的具体实现原理,详细的阐述 DR 模式是如何工作的。

img

其实 DR 是最常用的工作模式,因为它的强大的性能。下边以一次请求和响应数据流的过程来描述 DR 模式的具体原理。

(一)实现原理过程

① 当客户端请求 www.sina.com.cn 主页,经过 DNS 解析到 IP 后,向新浪服务器发送请求数据,数据包经过层层网络到达新浪负载均衡 LVS 服务器,到达 LVS 网卡时的数据包:源 IP 是客户端 IP 地址 CIP,目的 IP 是新浪对外的服务器 IP 地址,也就是 VIP;此时源 MAC 地址是 CMAC,其实是 LVS 连接的路由器的 MAC 地址(为了容易理解记为 CMAC),目标 MAC 地址是 VIP 对应的 MAC,记为 VMAC。

② 数据包到达网卡后,经过链路层到达 PREROUTING 位置(刚进入网络层),查找路由发现目的 IP 是 LVS 的 VIP,就会递送到 INPUT 链上,此时数据包 MAC、IP、Port 都没有修改。

③ 数据包到达 INPUT 链,INPUT 是 LVS 主要工作的位置。此时 LVS 会根据目的 IP 和 Port 来确认是否是 LVS 定义的服务,如果是定义过的 VIP 服务,就会根据配置的 Service 信息,从 RealServer 中选择一个作为后端服务器 RS1,然后以 RS1 作为目标查找 Out 方向的路由,确定一下跳信息以及数据包要通过哪个网卡发出。最后将数据包通过 INET_HOOK 到 OUTPUT 链上(Out 方向刚从四层进入网络层)。

④ 数据包通过 POSTROUTING 链后,从网络层转到链路层,将目的 MAC 地址修改为 RealServer 服务器 MAC 地址,记为 RMAC;而源 MAC 地址修改为 LVS 与 RS 同网段的 selfIP 对应的 MAC 地址,记为 DMAC。此时,数据包通过交换机转发给了 RealServer 服务器(注:为了简单图中没有画交换机)。

⑤ 请求数据包到达 RealServer 服务器后,链路层检查目的 MAC 是自己网卡地址。到了网络层,查找路由,目的 IP 是 VIP(lo 上配置了 VIP),判定是本地主机的数据包,经过协议栈后拷贝至应用程序(比如这里是 nginx 服务器),nginx 响应请求后,产生响应数据包。以目的 VIP 为 dst 查找 Out 路由,确定吓一跳信息和发送网卡设备信息,发送数据包。此时数据包源、目的 IP 分别是 VIP、CIP,而源 MAC 地址是 RS1 的 RMAC,目的 MAC 是下一跳(路由器)的 MAC 地址,记为 CMAC(为了容易理解,记为 CMAC)。然后数据包通过 RS 相连的路由器转发给真正客户端。

从整个过程可以看出,DR 模式 LVS 逻辑非常简单,数据包通过路由方式直接转发给 RS,而且响应数据包是由 RS 服务器直接发送给客户端,不经过 LVS。我们知道一般请求数据包会比较小,响应报文较大,经过 LVS 的数据包基本上都是小包,上述几条因素是 LVS 的 DR 模式性能强大的主要原因。

(二)优缺点和使用场景

3.4 NAT 模式实现原理

lvs 的第 2 种工作模式是 NAT 模式,下图详细介绍了数据包从客户端进入 lvs 后转发到 rs,后经 rs 再次将响应数据转发给 lvs,由 lvs 将数据包回复给客户端的整个过程。

img

(一)实现原理与过程

① 用户请求数据包经过层层网络,到达 lvs 网卡,此时数据包源 IP 是 CIP,目的 IP 是 VIP。

② 经过网卡进入网络层 prerouting 位置,根据目的 IP 查找路由,确认是本机 IP,将数据包转发到 INPUT 上,此时源、目的 IP 都未发生变化。

③ 到达 lvs 后,通过目的 IP 和目的 port 查找是否为 IPVS 服务。若是 IPVS 服务,则会选择一个 RS 作为后端服务器,将数据包目的 IP 修改为 RIP,并以 RIP 为目的 IP 查找路由信息,确定下一跳和出口信息,将数据包转发至 output 上。

④ 修改后的数据包经过 postrouting 和链路层处理后,到达 RS 服务器,此时的数据包源 IP 是 CIP,目的 IP 是 RIP。

⑤ 到达 RS 服务器的数据包经过链路层和网络层检查后,被送往用户空间 nginx 程序。nginx 程序处理完毕,发送响应数据包,由于 RS 上默认网关配置为 lvs 设备 IP,所以 nginx 服务器会将数据包转发至下一跳,也就是 lvs 服务器。此时数据包源 IP 是 RIP,目的 IP 是 CIP。

⑥ lvs 服务器收到 RS 响应数据包后,根据路由查找,发现目的 IP 不是本机 IP,且 lvs 服务器开启了转发模式,所以将数据包转发给 forward 链,此时数据包未作修改。

⑦ lvs 收到响应数据包后,根据目的 IP 和目的 port 查找服务和连接表,将源 IP 改为 VIP,通过路由查找,确定下一跳和出口信息,将数据包发送至网关,经过复杂的网络到达用户客户端,最终完成了一次请求和响应的交互。

NAT 模式双向流量都经过 LVS,因此 NAT 模式性能会存在一定的瓶颈。不过与其它模式区别的是,NAT 支持端口映射,且支持 windows 操作系统。

(二)优点、缺点与使用场景

**3.5 Tunnel 模式实现原理****

Tunnel 模式在国内使用的比较少,不过据说腾讯使用了大量的 Tunnel 模式。它也是一种单臂的模式,只有请求数据会经过 lvs,响应数据直接从后端服务器发送给客户端,性能也很强大,同时支持跨机房。下边继续看图分析原理。

img

(一)实现原理与过程

① 用户请求数据包经过多层网络,到达 lvs 网卡,此时数据包源 IP 是 cip,目的 ip 是 vip。

② 经过网卡进入网络层 prerouting 位置,根据目的 ip 查找路由,确认是本机 ip,将数据包转发到 input 链上,到达 lvs,此时源、目的 ip 都未发生变化。

③ 到达 lvs 后,通过目的 ip 和目的 port 查找是否为 IPVS 服务。若是 IPVS 服务,则会选择一个 rs 作为后端服务器,以 rip 为目的 ip 查找路由信息,确定下一跳、dev 等信息,然后 IP 头部前边额外增加了一个 IP 头(以 dip 为源,rip 为目的 ip),将数据包转发至 output 上。

④ 数据包根据路由信息经最终经过 lvs 网卡,发送至路由器网关,通过网络到达后端服务器。

⑤ 后端服务器收到数据包后,ipip 模块将 Tunnel 头部卸载,正常看到的源 ip 是 cip,目的 ip 是 vip,由于在 tunl0 上配置 vip,路由查找后判定为本机 ip,送往应用程序。应用程序 nginx 正常响应数据后以 vip 为源 ip,cip 为目的 ip 数据包发送出网卡,最终到达客户端。

Tunnel 模式具备 DR 模式的高性能,又支持跨机房访问,听起来比较完美了。不过国内运营商有一定特色性,比如 RS 的响应数据包的源 IP 为 VIP,VIP 与后端服务器有可能存在跨运营商的情况,有可能被运营商的策略封掉。Tunnel 在生产环境确实没有使用过,在国内推行 Tunnel 可能会有一定的难度吧!

(二)优点、缺点与使用场景

3.6 涉及的概念术语

上述内容中涉及到很多术语或缩写,这里简单解释下具体的含义,便于理解。

基础性的原理知识,暂时理解到这里就可以了,下一篇以实践的方式来进一步了解 LVS 的工作原理和基本使用