在存储系统中为了提高后端设备的吞吐量,往往需要采用多网卡绑定技术。例如,后端存储最大能够提供300MB/s的吞吐量,因此需要采用3块1Gps的网卡并发传输才可以达到峰值性能。那么,从研发的角度来看如何实现多网卡绑定呢?这里对提高吞吐量用途的多网卡绑定技术进行深入分析。
多网卡绑定一方面能够提高网络吞吐量,另一方面也可以增强网络高可用。这里对高可用应用的多网卡绑定技术不做讨论。从软件的角度来看,多网卡绑定实际上只需要提供一个额外的bond驱动程序即可,通过该虚拟网卡驱动程序可以将实际多块网卡屏蔽,对TCP/IP协议层而言只存在一个Bond网卡。在Bond驱动程序中实现网络流量的负载平衡(load balance),将一个网络请求重定位到不同的网卡(NIC)上,以此来提高总体网络的性能。多网卡绑定的软件层次架构如下图所示:
考虑一下,为了绑定多块网卡,其技术难点在于什么地方?网络交换机是通过物理地址进行端口路由的,对于不支持IEEE802.3ab协议的普通交换机而言,其只能连接不同物理地址的网卡,否则交换机将会无法正常工作。每个网络适配器具备一个IP地址,而每个IP地址又通过ARP协议和一个MAC地址绑定在一起。由此分析,在没有交换机的配合下,我们很难实现想象中完美的多网卡绑定通信模型:
如果ARP协议能够支持将一个IP地址映射到多个MAC地址,那么在Bond驱动层我们完全可以实现上图所示的多网卡绑定通信模型。在实际IP网络中,为了达到上述绑定效果,需要交换机的802.3ab协议支持,通过交换机实现round robin方式的网卡绑定,纯软件方法无法做到。基于802.3ab协议的多网卡绑定如下图所示:
在802.3ab的支持下,Server端所有网卡的MAC地址全部配置成一个,例如MAC-A,然后在交换机端将这些端口聚合起来。交换机在接收到数据报文之后会轮询这些端口将数据报文发送给Bond驱动,Bond驱动想发送数据的时候同样通过轮询方法将数据报文交给不同网卡进行传输。这种方法可以对Client端进行透明,从整体架构上来说比较简单,唯一缺点是需要交换机的支持。个人认为对于存储系统而言,这种方案是目前网卡绑定的最佳方式。
除了交换机支持的解决方案之外,当然我们也可以采用纯软件的方法,只不过这种绑定在有些应用中有所局限。一种比较简单的绑定思想是只对Transmit进行绑定(Linux Bond5 Mode)。该绑定模型如下图所示:
在这种模型中,Client向Server发送ARP请求,Server将Bond适配器的MAC地址告诉给Client。Bond适配器驱动程序会选择一个Slave-NIC的MAC地址作为自己的MAC地址。例如,Client-B向Server发送ARP请求,Server会将MAC-C地址告诉给Client-B。因此,Client端发送的数据报文会全部被MAC-C地址所在的NIC接收。换句话说,所有Client了解到Server的MAC地址都是MAC-C,Client看不到Server端其他NIC的MAC地址。在Server端发送数据报文的时候,Server端封装的Source-Address都是Bond适配器配置的MAC地址,目的地址是Client NIC所在的MAC地址。在数据发送的时候,Bond驱动程序会根据一定算法将发送报文均匀分配到所有NIC上,由于NIC驱动不会更改以太网报文中的内容,通过这种方式,Bond驱动可以充分利用所有网卡的物理带宽。这种方法实现简单,Bond驱动程序不需要截获传输报文的任何数据,只需要选择网卡进行数据传输即可。由于Client只知道一个网卡的物理地址,所以无法实现多网卡的并发数据接收,只能实现并发数据发送。对于只关注数据发送吞吐量的应用,这种解决方案还是非常有效的。
在存储应用中,需要考虑双向数据传输的吞吐量,上述解决方案存在数据接收瓶颈。那么如何才能使得Server进行高效的双向数据传输呢?其关键问题在于需要让Client知道不同网卡的MAC地址,上述解决方案中,所有的Client只知道一个MAC地址。为了达到双向传输的效果,Bond驱动程序需要截取ARP报文和数据报文,并且修改MAC地址。这种网卡绑定的数据传输模型(Linux Bond6 Mode)如下图所示:
在Client向Server发送ARP请求的时候,Bond驱动程序会截取返回给Client的ARP应答报文,并且选取一个Slave-NIC的MAC地址,用这个MAC地址修改ARP应答报文。通过这种方式,Server将一块网卡分配给一个Client,每个Client分配得到不同NIC的MAC地址,从而Client可以通过不同的网卡实现数据传输。在多Client的情况下,实现Server端并发数据接收。在Server端数据发送的时候,Bond驱动程序需要截取发送数据报文,并且修改以太网报文中的源MAC地址(bond_alb_xmit函数实现了Bond的数据发送功能),然后通过算法选择一块NIC发送数据,实现并发数据传输(数据报文发送并不固定在一块网卡上,上图的演示模型只是一个特例)。这种方案和上述方案最大的不同是Bond驱动程序需要截获ARP和正常的数据报文,并进行处理。从Client而言,每个Client的数据发送可以绑定到一个单独的NIC卡上。
这里对多网卡的绑定技术进行了一些总结,这些技术还是值得慢慢品味的。