深入浅出 LVS 负载均衡系列概览(已完结)
📌 本系列按照负载均衡器对数据包的处理方式分类,从计算机间通信的角度出发,浅谈 NAT、FULLNAT、DR、TUN 模型的实现原理。
LVS(Linux Virtual Server) 是一个虚拟服务器集群系统。工作在 OSI 模型的传输层,即四层负载均衡。LVS 本身实现了 NAT、DR、TUN 模型,这些模型仅做数据包的转发,而不会与客户端建立连接,成本低效率高。FULLNAT 基于 NAT 实现,LVS 本身不支持,需要额外对内核打补丁后才能使用。
两台计算机如何在互联网中通信
在了解 LVS 负载均衡之前,先要搞清楚两台计算机如何在互联网中通信。茫茫互联网中,两台计算机如何才能找到对方?
我们先来看看,快递是如何被快递小哥完美地送到你手上的。根据你的地址,快递先送到你所在的省市区,接着在当前省市区找到你的门牌号,最后根据门牌号和姓名,再亲手把快递交给你。
两台计算机在互联网中的通信也是如此。首先需要知道双方的 IP 地址,即省市区,其次需要知道双方的 MAC 地址,即门牌号。MAC 地址标志着唯一的计算机。在同一台计算机上,可能有多个不同的服务,如何能像快递小哥按照姓名找到你一样,在计算机上找到对应的服务呢?没错,就是按照端口号。
这样,通信中每台计算机需要提供的信息就很清晰了,即 IP 地址、MAC 地址、端口号。总结一下,通信必需的六个要素就是,源 IP 地址、端口号、源 MAC 地址,目标 IP 地址、端口号、目标 MAC 地址。
假设计算机 A 和计算机 B 在上述的网络拓扑图(不在同一局域网)中。可以很清晰地看到 计算机 A 和 计算机 B 通信需要五个步骤,其中 ①② 和 ④⑤ 的原理相同。现在我们来看看具体的每个步骤在计算机的世界中是如何实现的。
首先 A 和 B 的 IP 地址和端口号是已知的,即一个数据包从哪来要发往哪去。所以现在的问题是:A 如何能知道 B 的 MAC 地址?
最简单的方式就是 A 保存网络中全部设备的 MAC 地址,在发送时查询一下,这样就能得到 B 的 MAC 地址。但是网络中的设备有几十亿个,还在不断地增长,显然这种方式是不可取的。如果按照快递发送过程中,在每个驿站之间进行转移,这样只需要知道该发往的下一目的地在哪里,最终也能将快递成功地交到你的手上。在实际网络中发送数据包也是这样,现在的目标就是确定 “下一个目的地” 的 MAC 地址。
步骤 ①②:发送数据包至网关
A 不知道 B 的 MAC 地址,且 A 和 B 也不在同一个局域网中。这时 A 会根据 ARP 协议先发出一个广播包,即目标 MAC 地址是 FF:FF:FF:FF:FF:FF 的数据包。当 交换机 1 收到这个广播包之后,会将这个数据包转发给其他端口,并且记录 A 的 MAC 地址和交换机端口之间的映射关系,后续再看到这个 MAC 地址,就知道该从哪个端口转发出去。当 路由器 1 收到广播包后,会将自己的 MAC 地址返回。A 接收到返回后,就知道 “下一个目的地” 的 MAC 地址了。A 重新发送数据包,将目标 MAC 地址填写为 路由器 1 的 MAC 地址,并在本地的缓存表中记录返回的 MAC 地址。
💡 查看当前设备缓存表里已存的 MAC 地址:arp -a
📌 ARP 协议的目的就是找到 “下一个目的地” 的 MAC 地址,即 IP 地址和 MAC 地址之间的映射关系。 当两台设备同处于一个局域网时,“下一个目的地” 就是目标设备的 MAC 地址,当两台设备不处于同一个局域网时,“下一个目的地” 就是网关的 MAC 地址。
步骤 ③:网关间跳转
经过步骤 ①②,此时 路由器 1 收到的数据包为 {A_IP、PORT、A_MAC} ➡ { B_IP、PORT、路由器 1_MAC } 。收到数据包后,路由器 1 查看自己的路由表,如下图所示。
💡 查看当前设备设置的路由表:route -n
路由器 1 会将 B_IP 与 路由表中每条记录的子网掩码(Genmask)做按位与运算。如果得到的结果和目的网络(Destination)相同,那么 “下一个目的地 “ 的 MAC 地址,就是配置的网关(Gateway)的 MAC 地址,这种找到相邻网络的方式叫做 “下一跳机制”。如果网关的地址为 0.0.0.0,说明可以在局域网中直接通信,不需要 “下一跳”。至此,再次找到了 “下一个目的地” 的 MAC 地址,即 路由器 2 的 MAC 地址。此时 路由器 2 收到的数据包为 { A_IP、PORT、路由器 1_MAC } ➡ { B_IP、PORT、路由器 2_MAC } 。步骤 ④⑤ 和 ①② 的原理相同,在这里就不赘述了。
📌 下一跳的目的就是找到 “下一个目的地”,即下一步该到达哪里,侧重 “路线” 的选择,并由此获取到对应的 MAC 地址,继续传送数据包。
总结一下:
当然,光是找到对方还不够,还需要一个约定的交流方式,平时我们所熟知的各种协议,都是计算机「约定的交流方式」。
LVS 负载均衡
随着使用互联网的设备不断增长,服务端对应接收到的 HTTP 请求更是呈指数型的增长。当一台服务器无法承载非常大的请求量时,使用多台服务器来分摊请求。将请求分摊给多台服务器的行为,就称之为负载均衡。
从网络中计算机通信的角度,而非使用更上层的应用(如 Nginx)出发,搭建四层负载均衡器后,数据包的发送链路为:CIP ➡️ VIP ➡️ DIP ➡️ RIP,即 客户端 IP ➡️ 虚拟 IP ➡️ 分发 IP ➡️ 真实服务器 IP。对于客户端来说,只需要知道请求到达的地址是 VIP,不需要考虑负载,即 CIP ➡️ VIP 是固定的。
所以负载均衡器要做的事情,就是将 CIP 发送到 VIP 的数据包,经由 DIP 转发给 RIP,服务响应后再将响应的数据包返回给 CIP。
NAT 模式
红色,表示发出的数据包
绿色,表示返回的数据包
黄色,表示负载均衡器修改的内容
虚线,表示经过 N 个下一跳,即可以不在同一局域网内
实线表,示只能 “跳跃一次”,即必须在同一局域网内
总结一下 NAT 模式的特点:
FULLNAT 模式
NAT 模式中,负载均衡器和真实服务器必须在同一局域网内,但在实际的开发过程中,真实服务器可能分布在不同的网段,甚至不同的城市。如何能将 NAT 模式应用在真实服务器分布在不同网段的场景下?
红色,表示发出的数据包
绿色,表示返回的数据包
黄色,表示负载均衡器修改的内容
虚线,表示经过 N 个下一跳,即可以不在同一局域网内
实线,表示只能 “跳跃一次”,即必须在同一局域网
总结一下 FULL NAT 模式的特点:
可以看到在 NAT 和 FULLNAT 模式中,不管是请求数据包还是响应数据包,都要经过负载均衡器。但是响应数据包一般要比请求数据包大很多,这可能会成为系统的瓶颈。如果能够将请求数据包转发到真实服务器之后,响应数据包由真实服务器直接返回,这样对负载均衡器的压力就小很多。这种模式又该如何实现?
原创不易,期待点赞收藏,任何建议欢迎评论区交流~
more about me