负载均衡(Load Balancing) 调度后方的老多台机器,以统一的生常接口对外提供服务
,承担此职责的负载技术组件被称为“负载均衡” 。 在互联网时代的均衡早期 ,网站流量还相对较小 ,老并且业务也比较简单,生常单台服务器便有可能满足访问需要
,负载但时至今日,均衡互联网应用也好,老企业级应用也好
,生常一般实际用于生产的负载系统,几乎都离不开集群部署了。服务器租用均衡信息系统不论是老采用单体架构多副本部署还是微服务架构,不论是生常为了实现高可用还是为了获得高性能,都需要利用到多台机器来扩展服务能力,负载希望用户的请求不管连接到哪台机器上
,都能得到相同的处理。另一方面 ,如何构建和调度服务集群这事情
,又必须对用户一侧保持足够的透明
,即使请求背后是源码库由一千台、一万台机器来共同响应的,也绝非用户所关心的事情
,用户需记住的只有一个域名地址而已。调度后方的多台机器,以统一的接口对外提供服务,承担此职责的技术组件被称为“负载均衡”(Load Balancing)。 真正大型系统的负载均衡过程往往是多级的免费模板 。譬如,在各地建有多个机房 ,或机房有不同网络链路入口的大型互联网站
,会从 DNS 解析开始 ,通过“域名” → “CNAME” → “负载调度服务” → “就近的数据中心入口”的路径,先将来访地用户根据 IP 地址(或者其他条件)分配到一个合适的数据中心中
,然后才到稍后将要讨论的各式负载均衡。在 DNS 层面的负载均衡与前面介绍的 DNS 智能线路、源码下载内容分发网络等,在工作原理上是类似的 ,其差别只是数据中心能提供的不仅有缓存,而是全方位的服务能力。后续我们所讨论的“负载均衡”只聚焦于网络请求进入数据中心入口之后的其他级次的负载均衡。 无论在网关内部建立了多少级的负载均衡
,香港云服务器从形式上来说都可以分为两种
:四层负载均衡和七层负载均衡。在详细介绍它们是什么以及如何工作之前 ,我们先来建立两个总体的、概念性的印象 。 我们所说的“四层”、“七层”,指的是经典的OSI 七层模型中第四层传输层和第七层应用层,表 4-1 是来自于维基百科上对 OSI 七层模型的介绍(笔者做了简单的中文翻译),这部分属于网络基础知识,这里就不多解释了。后面我们会多次使用到这张表 ,如你对网络知识并不是特别了解的,可通过维基百科获得进一步的资料 。 表4-1 OSI七层模型 现在所说的“四层负载均衡”其实是多种均衡器工作模式的统称 ,“四层”的意思是说这些工作模式的共同特点是维持着同一个 TCP 连接 ,而不是说它只工作在第四层。事实上,这些模式主要都是工作在二层(数据链路层,改写 MAC 地址)和三层(网络层,改写 IP 地址)上,单纯只处理第四层(传输层,可以改写 TCP 、UDP 等协议的内容和端口)的数据无法做到负载均衡的转发,因为 OSI 的下三层是媒体层(Media Layers),上四层是主机层(Host Layers)
,既然流量都已经到达目标主机上了
,也就谈不上什么流量转发
,最多只能做代理了
。但出于习惯和方便,现在几乎所有的资料都把它们统称为四层负载均衡,笔者也同样称呼它为四层负载均衡,如果读者在某些资料上看见“二层负载均衡”、“三层负载均衡”的表述
,应该了解这是在描述它们工作的层次,与这里说的“四层负载均衡”并不是同一类意思 。下面笔者来介绍几种常见的四层负载均衡的工作模式。 参考上面 OSI 模型的表格 ,数据链路层传输的内容是数据帧(Frame) ,譬如常见的以太网帧、ADSL 宽带的 PPP 帧等。我们讨论的具体上下文里
,目标必定就是以太网帧了,按照IEEE 802.3标准
,最典型的 1500 Bytes MTU 的以太网帧结构如表 4-2 所示 。 表4-2 最典型的1500 Bytes MTU的以太网帧结构说明 帧结构中其他数据项的含义在本节中可以暂时不去理会,只需注意到“MAC 目标地址”和“MAC 源地址”两项即可。我们知道每一块网卡都有独立的 MAC 地址 ,以太帧上这两个地址告诉了交换机 ,此帧应该是从连接在交换机上的哪个端口的网卡发出
,送至哪块网卡的。 数据链路层负载均衡所做的工作 ,是修改请求的数据帧中的 MAC 目标地址,让用户原本是发送给负载均衡器的请求的数据帧
,被二层交换机根据新的 MAC 目标地址转发到服务器集群中对应的服务器(后文称为“真实服务器”,Real Server)的网卡上,这样真实服务器就获得了一个原本目标并不是发送给它的数据帧
。 由于二层负载均衡器在转发请求过程中只修改了帧的 MAC 目标地址
,不涉及更上层协议(没有修改 Payload 的数据),所以在更上层(第三层)看来,所有数据都是未曾被改变过的。由于第三层的数据包,即 IP 数据包中包含了源(客户端)和目标(均衡器)的 IP 地址 ,只有真实服务器保证自己的 IP 地址与数据包中的目标 IP 地址一致,这个数据包才能被正确处理
。因此
,使用这种负载均衡模式时,需要把真实物理服务器集群所有机器的虚拟 IP 地址(Virtual IP Address,VIP)配置成与负载均衡器的虚拟 IP 一样,这样经均衡器转发后的数据包就能在真实服务器中顺利地使用。也正是因为实际处理请求的真实物理服务器 IP 和数据请求中的目的 IP 是一致的
,所以响应结果就不再需要通过负载均衡服务器进行地址交换,可将响应结果的数据包直接从真实服务器返回给用户的客户端,避免负载均衡器网卡带宽成为瓶颈,因此数据链路层的负载均衡效率是相当高的
。整个请求到响应的过程如图 4-8 所示。 图 4-8 数据链路层负载均衡 上述只有请求经过负载均衡器,而服务的响应无须从负载均衡器原路返回的工作模式,整个请求、转发 、响应的链路形成一个“三角关系”,所以这种负载均衡模式也常被很形象地称为“三角传输模式”(Direct Server Return,DSR),也有叫“单臂模式”(Single Legged Mode)或者“直接路由”(Direct Routing)。 虽然数据链路层负载均衡效率很高
,但它并不能适用于所有的场合,除了那些需要感知应用层协议信息的负载均衡场景它无法胜任外(所有的四层负载均衡器都无法胜任,将在后续介绍七层均衡器时一并解释),它在网络一侧受到的约束也很大 。二层负载均衡器直接改写目标 MAC 地址的工作原理决定了它与真实的服务器的通信必须是二层可达的
,通俗地说就是必须位于同一个子网当中,无法跨 VLAN。优势(效率高)和劣势(不能跨子网)共同决定了数据链路层负载均衡最适合用来做数据中心的第一级均衡设备,用来连接其他的下级负载均衡器。 根据 OSI 七层模型,在第三层网络层传输的单位是分组数据包(Packets),这是一种在分组交换网络(Packet Switching Network ,PSN)中传输的结构化数据单位
。以 IP 协议为例
,一个 IP 数据包由 Headers 和 Payload 两部分组成, Headers 长度最大为 60 Bytes,其中包括了 20 Bytes 的固定数据和最长不超过 40 Bytes 的可选的额外设置组成。按照 IPv4 标准 ,一个典型的分组数据包的 Headers 部分具有如表 4-3 所示的结构。 表4-3 分组数据包的Headers部分说明 在本节中,无须过多关注表格中的其他信息,只要知道在 IP 分组数据包的 Headers 带有源和目标的 IP 地址即可
。源和目标 IP 地址代表了数据是从分组交换网络中哪台机器发送到哪台机器的,我们可以沿用与二层改写 MAC 地址相似的思路,通过改变这里面的 IP 地址来实现数据包的转发 。具体有两种常见的修改方式。 第一种是保持原来的数据包不变
,新创建一个数据包
,把原来数据包的 Headers 和 Payload 整体作为另一个新的数据包的 Payload ,在这个新数据包的 Headers 中写入真实服务器的 IP 作为目标地址
,然后把它发送出去。经过三层交换机的转发 ,真实服务器收到数据包后 ,必须在接收入口处设计一个针对性的拆包机制,把由负载均衡器自动添加的那层 Headers 扔掉,还原出原来的数据包来进行使用
。这样,真实服务器就同样拿到了一个原本不是发给它(目标 IP 不是它)的数据包,达到了流量转发的目的。那时候还没有流行起“禁止套娃”的梗,所以设计者给这种“套娃式”的传输起名叫做“IP 隧道”(IP Tunnel)传输,也还是相当的形象。 尽管因为要封装新的数据包,IP 隧道的转发模式比起直接路由模式效率会有所下降,但由于并没有修改原有数据包中的任何信息,所以 IP 隧道的转发模式仍然具备三角传输的特性,即负载均衡器转发来的请求
,可以由真实服务器去直接应答,无须在经过均衡器原路返回 。而且由于 IP 隧道工作在网络层,所以可以跨越 VLAN,因此摆脱了直接路由模式中网络侧的约束 。此模式从请求到响应的过程如图 4-9 所示。 图 4-9 IP 隧道模式的负载均衡 而这种转发方式也有缺点。第一个缺点是它要求真实服务器必须支持“IP 隧道协议”(IP Encapsulation) ,就是它得学会自己拆包扔掉一层 Headers,这个其实并不是什么大问题,现在几乎所有的 Linux 系统都支持 IP 隧道协议
。另外一个缺点是这种模式仍必须通过专门的配置
,必须保证所有的真实服务器与均衡器有着相同的虚拟 IP 地址,因为回复该数据包时
,需要使用这个虚拟 IP 作为响应数据包的源地址,这样客户端收到这个数据包时才能正确解析。这个限制就相对麻烦一些,它与“透明”的原则冲突,需由系统管理员介入。 而且
,对服务器进行虚拟 IP 的配置并不是在任何情况下都可行的,尤其是当有好几个服务共用一台物理服务器的时候,此时就必须考虑第二种修改方式——改变目标数据包:直接把数据包 Headers 中的目标地址改掉,修改后原本由用户发给均衡器的数据包 ,也会被三层交换机转发送到真实服务器的网卡上 ,而且因为没有经过 IP 隧道的额外包装,也就无须再拆包了。但问题是这种模式是通过修改目标 IP 地址才到达真实服务器的,如果真实服务器直接将应答包返回客户端的话
,这个应答数据包的源 IP 是真实服务器的 IP,也即均衡器修改以后的 IP 地址,客户端不可能认识该 IP ,自然就无法再正常处理这个应答了。因此,只能让应答流量继续回到负载均衡,由负载均衡把应答包的源 IP 改回自己的 IP,再发给客户端,这样才能保证客户端与真实服务器之间的正常通信。如果你对网络知识有些了解的话,肯定会觉得这种处理似曾相识,这不就是在家里
、公司、学校上网时 ,由一台路由器带着一群内网机器上网的“网络地址转换”(Network Address Translation,NAT)操作吗?这种负载均衡的模式的确被称为 NAT 模式,此时 ,负载均衡器就是充当了家里
、公司、学校的上网路由器的作用
。NAT 模式的负载均衡器运维起来十分简单,只要机器将自己的网关地址设置为均衡器地址,就无须再进行任何额外设置了。此模式从请求到响应的过程如图 4-10 所示 。 图 4-10 NAT 模式的负载均衡 在流量压力比较大的时候,NAT 模式的负载均衡会带来较大的性能损失,比起直接路由和 IP 隧道模式,甚至会出现数量级上的下降。这点是显而易见的,由负载均衡器代表整个服务集群来进行应答,各个服务器的响应数据都会互相挣抢均衡器的出口带宽,这就好比在家里用 NAT 上网的话
,如果有人在下载,你打游戏可能就会觉得卡顿是一个道理 ,此时整个系统的瓶颈很容易就出现在负载均衡器上
。 还有一种更加彻底的 NAT 模式 :即均衡器在转发时,不仅修改目标 IP 地址
,连源 IP 地址也一起改了,源地址就改成均衡器自己的 IP,称作 Source NAT(SNAT)。这样做的好处是真实服务器无须配置网关就能够让应答流量经过正常的三层路由回到负载均衡器上,做到了彻底的透明。但是缺点是由于做了 SNAT,真实服务器处理请求时就无法拿到客户端的 IP 地址了
,从真实服务器的视角看来,所有的流量都来自于负载均衡器 ,这样有一些需要根据目标 IP 进行控制的业务逻辑就无法进行。 前面介绍的四层负载均衡工作模式都属于“转发”
,即直接将承载着 TCP 报文的底层数据格式(IP 数据包或以太网帧)转发到真实服务器上 ,此时客户端到响应请求的真实服务器维持着同一条 TCP 通道。但工作在四层之后的负载均衡模式就无法再进行转发了
,只能进行代理,此时真实服务器、负载均衡器
、客户端三者之间由两条独立的 TCP 通道来维持通信,转发与代理的区别如图 4-11 所示
。 图 4-11 转发与代理 “代理”这个词
,根据“哪一方能感知到”的原则,可以分为“正向代理”、“反向代理”和“透明代理”三类
。正向代理就是我们通常简称的代理 ,指在客户端设置的、代表客户端与服务器通信的代理服务,它是客户端可知,而对服务器透明的。反向代理是指在设置在服务器这一侧,代表真实服务器来与客户端通信的代理服务 ,此时它对客户端来说是透明的 。至于透明代理是指对双方都透明的,配置在网络中间设备上的代理服务
,譬如,架设在路由器上的透明翻墙代理。 根据以上定义,很显然 ,七层负载均衡器它就属于反向代理中的一种
,如果只论网络性能,七层均衡器肯定是无论如何比不过四层均衡器的,它比四层均衡器至少多一轮 TCP 握手
,有着跟 NAT 转发模式一样的带宽问题,而且通常要耗费更多的 CPU,因为可用的解析规则远比四层丰富。所以如果用七层均衡器去做下载站、视频站这种流量应用是不合适的,起码不能作为第一级均衡器。但是,如果网站的性能瓶颈并不在于网络性能 ,要论整个服务集群对外所体现出来的服务性能
,七层均衡器就有它的用武之地了。这里面七层均衡器的底气就是来源于它工作在应用层,可以感知应用层通信的具体内容,往往能够做出更明智的决策 ,玩出更多的花样来
。 举个生活中的例子,四层均衡器就像银行的自助排号机,转发效率高且不知疲倦 ,每一个达到银行的客户根据排号机的顺序
,选择对应的窗口接受服务;而七层均衡器就像银行大堂经理
,他会先确认客户需要办理的业务,再安排排号。这样办理理财
、存取款等业务的客户 ,会根据银行内部资源得到统一协调处理,加快客户业务办理流程,有一些无须柜台办理的业务 ,由大堂经理直接就可以解决了,譬如 ,反向代理的就能够实现静态资源缓存 ,对于静态资源的请求就可以在反向代理上直接返回 ,无须转发到真实服务器。 代理的工作模式相信大家应该是比较熟悉的,这里不再展开,只是简单列举了一些七层代理可以实现的功能
,以便读者对它“功能强大”有个直观的感受。 负载均衡的两大职责是“选择谁来处理用户请求”和“将用户请求转发过去”
。到此我们仅介绍了后者,即请求的转发或代理过程 。前者是指均衡器所采取的均衡策略,由于这一块涉及的均衡算法太多,笔者无法逐一展开,所以本节仅从功能和应用的角度去介绍一些常见的均衡策略
。 从实现角度来看,负载均衡器的实现分为“软件均衡器”和“硬件均衡器”两类。在软件均衡器方面,又分为直接建设在操作系统内核的均衡器和应用程序形式的均衡器两种
。前者的代表是 LVS(Linux Virtual Server),后者的代表有 Nginx 、HAProxy、KeepAlived 等,前者性能会更好 ,因为无须在内核空间和应用空间中来回复制数据包;而后者的优势是选择广泛,使用方便 ,功能不受限于内核版本。 在硬件均衡器方面
,往往会直接采用应用专用集成电路(Application Specific Integrated Circuit,ASIC)来实现,有专用处理芯片的支持
,避免操作系统层面的损耗
,得以达到最高的性能。这类的代表就是著名的 F5 和 A10 公司的负载均衡产品。





