TCP/IP的主要缺点

毫无疑问,TCP/IP网络是当前主流的数据传输技术。传统的TCP/IP技术需要将数据从用户应用空间的Buffer复制到内核空间的Socket Buffer中,并进行头部的封装等操作,通过一系列多层网络协议的数据包处理工作,这些协议包括传输层的传输控制协议(TCP)、用户数据报协议(UDP)、网络层的互联网协议(IP)以及互联网控制消息协议(ICMP)等。数据才被复制到NIC网卡中的Buffer进行网络传输。在整个过程中,多项处理过程都很容易成为传输的瓶颈,它们包括:

  • 两次数据复制操作增加了CPU资源的消耗,并且传输带宽容易受到CPU处理速度的限制(这是最主要的原因),从用户模式到内核模式也需要进行上下文切换,这也是一个比较大的开销,同时这种冗余的处理增加了传输的延迟;
  • 头部的封装操作加大了CPU的资源消耗。

基于这些TCP/IP的缺点,有多种其他的传输方式可以作为TCP/IP的替代来进行高性能传输

TCP Offloading Engine

主要思想是将CPU从繁杂的网络处理过程中解放出来,将专用的处理过程offload到专用网卡上进行处理,使主机CPU专注于其它应用。这种技术需要特定网络接口——网卡支持这种offloading操作。这种特定网卡能够支持封装多层网络协议的数据包,这个功能常见于高速以太网接口上,如吉比特以太网(GbE)或10吉比特以太网(10GbE)。相对于使用传统的TCP/IP内核网络,这种方法的优点主要有两点:

  • 一是减少了数据复制的次数,原先需要复制两次,这次只需要将数据复制到网卡即可。TCP Offloading Engine是一种Zero-copy的协议;
  • 二是缓和了CPU的资源,也就是将CPU从网络处理中解放了出来;

主要缺点有两点:

  • 这种网卡需要专门进行设计;
  • 作为外设的这种专用网卡访问内存仍旧绕不开CPU,所以CPU访问内存的速度仍旧限制了网络的传输速度。

RDMA

为了将内存的访问从CPU中解放开来,RDMA技术结合了TCP Offloading Engine和DMA技术,使得CPU从数据包复制和内存访问中都解放了开来。

In general, the drawback of offloading technologies is getting data to and from the accelerating hardware. This is where Direct Memory Access, or DMA comes in. DMA has long been utilized in hardware such as disk drives. As the name implies DMA allows a device to have direct access to memory without needing to utilize the CPU.

通常来说,RDMA被认为包含三个主要的方面:

  • Zero-copy:也就是RDMA在发送数据时不需要拷贝,这意味着数据可以直接从用户空间发送。Zero-copy的意思是不需要将数据拷贝到内核中,但是仍旧需要将数据发送到网卡中进行传输,也就是节省了TCP第一部分复制的开销;
  • OS-bypass:也就是RDMA可以越过操作系统来发送数据;
  • Protocol offload:也就是RDMA可以将协议卸载到网卡上。

User-Net Networking(U-Net)

U-Net的设计目标是将协议处理部分移动到用户空间去处理。这种方式避免了用户空间将数据移动和复制到内核空间的开销。也就是降低了一次复制开销。U-Net是RDMA项目早期的一种设计,相对于TCP Offloading Engine,U-Net将网络协议实现在用户端而不是网卡上。U-Net也是一种Zero-copy的协议,

为什么TCP协议栈要放在Linux内核中呢?

让我们从一个更广泛的问题开始:运行操作系统到底有什么意义?如果计划运行一个应用程序,则必须使用由数百万行代码组成的内核,这似乎是一种负担。

但是实际上,我们大多数人都决定运行某种操作系统,我们这样做有两个原因。

  • 首先,操作系统层增加了硬件独立性和易于使用的API。有了这些,我们可以专注于为任何机器编写代码:不仅是我们目前拥有的专用硬件。
  • 其次,操作系统增加了一个时间共享层。这使我们可以一次运行多个应用程序。无论是启动第二个HTTP服务器还是只是启动第二个bash会话,在多个进程之间共享资源的能力至关重要。内核对外开放的所有资源都可以在多个进程之间共享!

通过使用通用的操作系统网络堆栈,我们能够运行多个网络应用程序。如果我们将网卡硬件专用于单个应用程序以运行用户空间的网络堆栈,则会丢失这种能力。如果网卡被一个进程所声明并使用,那么我们将不能够在运行服务器的同时运行SSH会话。

这听起来很不可思议,但这正是大多数现成的用户空间网络堆栈技术所面临的问题。用户空间网络堆栈技术的术语是“完全内核旁路”。其想法是绕过内核,直接从用户空间进程使用网络硬件。

在Linux相关的生态环境中,有一些可用的技术,但是并不是所有都是开源的,比如:PF_RING, Snabbswitch, DPDK, Netmap等等。

所有这些技术都需要将整个网卡移交给一个进程。换句话说:我们完全有可能编写自己的网络堆栈,使其专注于我们所需要的特定功能,并针对性能进行优化。但是这会产生很大的成本:您将被限制为每个网卡最多运行一个进程。

但是即使有所有这些不足之处,我也不能忽略内核旁路的好处。许多人确实运行自定义的网络堆栈,原因是以下两个原因之一:延迟和高性能(更低的CPU开销、更高的吞吐率)。

综合来看,我们可以概括为以下两点:

  • 如果是小型设备,需求是通用的,那么使用内核协议栈;
  • 如果是大型设备/数据中心,需求是固定/特定的,那么使用DPDK等用户态协议栈,结合网络虚拟化技术,会获得最适合的性能。

参考文献