4.5.2 网络层负载均衡
根据OSI七层模型,在第三层网络层传输的单位是分组数据包(Packet),这是一种在分组交换网络(Packet Switching Network,PSN)中传输的结构化数据单位。以IP协议为例,一个IP数据包由头部(Header)和荷载(Payload)两部分组成,Header的长度最大为60字节,其中包括20字节的固定数据和最长不超过40字节的可选数据。按照IPv4标准,一个典型的分组数据包的Header部分具有如表4-3所示的结构。
表4-3 分组数据包的Header部分说明
在本节,无须过多关注表格中的其他信息,只要知道在IP分组数据包的Header中带有源和目标的IP地址即可。源和目标IP地址说明了数据是从分组交换网络中哪台机器发送到哪台机器的,我们可以沿用与二层改写MAC地址相似的思路,通过改变这里面的IP地址来实现数据包的转发。具体有两种常见的修改方式。
第一种是保持原数据包不变,新创建一个数据包,把原数据包的Header和Payload整体作为新数据包的Payload,并在这个新数据包的Header中写入真实服务器的IP作为目标地址,然后把它发送出去。经过三层交换机的转发,真实服务器收到数据包后,必须在接收入口处设计一个针对性的拆包机制,把由负载均衡器自动添加的那层Header扔掉,还原出原数据包来进行使用。这样,真实服务器就同样拿到了一个原本不是发给它(目标IP不是它)的数据包,达到了流量转发的目的。当时还没有流行起“禁止套娃”的梗,所以设计者将这种“套娃式”的传输称为“IP隧道”(IP Tunnel)传输,也是相当的形象。
尽管因为要封装新的数据包,IP隧道转发模式的效率比直接路由模式的效率低,但由于并没有修改原数据包中的任何信息,所以IP隧道转发模式仍然具备三角传输的特性,即负载均衡器转发来的请求,可以由真实服务器去直接应答,无须经过负载均衡器原路返回。而且由于IP隧道工作在网络层,所以可以跨越VLAN,因此摆脱了直接路由模式中网络侧的约束。此模式从请求到响应的过程如图4-9所示。
图4-9 IP隧道模式的负载均衡
当然,这种转发模式也有缺点。第一个缺点是它要求真实服务器必须支持“IP隧道协议”(IP Encapsulation),即它得学会自己拆包扔掉一层Header,这个其实并不是什么大问题,现在几乎所有的Linux系统都支持IP隧道协议。另外一个缺点是这种模式仍必须通过专门的配置,必须保证所有的真实服务器与负载均衡器有相同的虚拟IP地址,因为回复该数据包时,需要使用这个虚拟IP作为响应数据包的源地址,这样客户端收到这个数据包时才能正确解析。这个限制就相对麻烦一些,它与“透明”的原则冲突,需由系统管理员介入。
而且,对服务器进行虚拟IP的配置并不是在任何情况下都可行的,尤其是当几个服务共用一台物理服务器的时候,此时就必须考虑第二种修改方式——改变目标数据包:直接修改数据包Header中的目标地址,修改后原本由用户发给负载均衡器的数据包也会被三层交换机转发到真实服务器的网卡上,而且因为没有经过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进行控制的业务逻辑就无法进行了。