NFV、DPDK以及部分用户态协议研究
本文为作者原创,转载请注明出处(http://www.cnblogs.com/mar-q/)by 负赑屃
对笔者而言,这是一个挺新的领域,比较有意思。
一、解释名词:
NFV(Network Function Virtualization):通过使用x86等通用性硬件以及虚拟化技术,来承载很多功能的软件处理。从而降低网络昂贵的设备成本。 这项技术的目的在于软硬件的解耦合,让网络设备功能不再依赖于底层硬件,为啥呢,因为硬件研发周期长,贵啊。
DPDK(Intel Data Plane Development Kit):Intel数据面开发包,它是一组快速处理数据包的开发平台接口。
二、我们的网络存在什么问题?
目前服务器并发量达到C10k是没有问题的,通过软件作出了比较好的解决方案,例如Nginx、Lighthttp等基于事件驱动的web框架和Tornado这类非阻塞web框架,都能够较好的解决万级别的用户请求。目前的非阻塞或者异步,原理上都是线程的异步模式,也就是说还是需要线程进行上下文切换,只不过区别在于内核何时产生中断。
但是这种异步模式到了C10M基本就不够用了,网络请求达到了千万级,这在以前也许是网络设备厂商需要考虑的事情,随着硬件设备的发展,越来越趋于模块的统一化。例如曾经网络专用处理器是Intel公司的主力产品线,诞生了IXP4xx~IXP28xx等一系列专用处理芯片,而在2006年左右,AMD和Intel曾经爆发过一场多核之战,随着新一代core架构的诞生(Intel要感谢以色列的工程师),这场战争基本宣告结束,但是在当时,AMD在技术上曾经一度领先,我的第一台电脑CPU就是AMD的。这次商业大战让Intel思考使用通用多核处理器取代IXP专用处理器,由此IXP的研发体系开始向Intel多核CPU转型,这为DPDK的诞生创造了条件。
为啥为Intel向通用CPU转型就会产生DPDK呢,因为使用通用的底层硬件我们就可以不必太关注底层,大家都是用的X86,都是用的RISC,所以更多的功能可以放在软件层面来完成,尤其是硬件开发成本和周期是远远超过软件的,所以何乐而不为呢。再回到前面的问题,为什么异步解决不了C10M的问题呢?因为线程的频繁调度是需要内核进行上下文切换的,而CPU是存在指令周期的,尤其是当Cache不命中的时候,切换上下文的指令周期会延长很多,要解决这个问题就要避开这种中断模式:即采用轮询的方式来提升性能。
从数据包角度分析:这就要求我们必须绕开现有的内核协议,因为现有的内核协议栈是基于中断模式的,如果要绕开内核,那就要解决驱动问题,解决网卡接口数据怎么到内存的问题,这些就是DPDK所提供的功能。
从多核角度分析:要尽量减少线程的调度和切换,最好每个OS进程绑定一个核,每个核上数据结构都大致相同,在NUMA架构(非一致性访存体系结构,分多节点,每个节点多个CPU,内部共享一个内存控制器)下提高访存速度。
从内存角度分析:要尽量减少Cache miss,如果每个用户占用2k空间,10M的用户将使用20g内存,这么多并发连接一定会产生Cache miss,一旦失效CPU运行时间会提高一个数量级,因此我们可以通过大页的方法,尽量把内存划分更少的块数,以此提高命中率。
综上,千万级数据包的处理思路就是:摒弃内核协议(PF_RING,Netmap,intelDPDK)、多核的OS绑定、内存大页。[1]
三、用户态协议
传统X86架构网络数据包处理是CPU中断方式:网卡驱动接收数据包->中断通知CPU处理->CPU拷贝数据并交给协议栈,当数据量大时会产生大量CPU中断,导致CPU无法运行其他程序。DPDK采用轮询方式处理:DPDK重载网卡驱动(接管网卡),DPDK接收数据包后不中断,直接将数据包通过零拷贝技术存入内存,应用层直接通过DPDK接口直接从内存读取数据包。 DPDK目前正在成为实现NFV的一项标杆技术,它主要为Intel architecture(IA)处理器架构下用户空间高效的数据包处理提供库函数和驱动的支持,它不同于Linux系统以通用性设计为目的,而是专注于网络应用中数据包的高性能处理,运行在用户空间上利用自身提供的数据平面库来收发数据包,绕过了Linux内核协议栈对数据包处理过程。[2]
需要注意的是,DPDK本身并不是一项协议,它不提供诸如IP协议、防火墙等网络协议功能,它只是我们在OS下的一套数据处理接口。因为多年来,高性能网络背后的传统思想就是将所有的数据包处理功能,尽可能的推向内核,数据报传输时需要跨越内核和用户,数据报中断产生的上下文切换和数据复制的成本都极大限制了数据报文处理的速度,所以我们可以用DPDK来绕过内核,这就是用户态协议要完成的工作。
为啥叫用户态协议呢?它和现有的TCP/IP协议有什么区别呢?简而言之就是现有的TCP/IP协议都是基于内核运行的,而用户态协议就是另外开发一套协议运行于内核之外。自2014年起在OSDI、NSDI、TOCS 等顶会期刊上出现了不少用户态协议,列举如下:
1. IX Project:Stanford & EPFL git、论文地址
IX是一个专门的数据面lib OS,解决了高吞吐量,低延迟,强大的保护和能源效率之间的4路权衡。IX使用硬件虚拟化将控制面与数据面分开,从而保持现有内核的健壮性。控制面负责资源分配,数据面负责提供高性能网络I / O。通过对事件驱动关键应用的延迟和吞吐量进行优化,主要方法是按批次绑定处理数据包,最小化这些连续传输,并保持多核同步。 IX的团队则认为不应信任那些直接访问设备的应用,一方面担心应用的稳定性,另一方面这种方式对网络安全产生的巨大威胁。因此IX通过Intel虚拟化扩展让I/O路径和应用程序代码共存,将队列映射到内核,但是仍然设法在隔离的保护域中运行网络堆栈,在这个隔离的保护域中,应用程序不能使用数据。
简而言之,IX自己实现了一个叫dune的安全核,因为需要使用硬件虚拟化,所以IX目前支持的网卡有限,我后续会发布测试的文章。
2. mTCP:KAIST(韩)git、论文地址
mTCP是一个基于多核的高性能用户态协议,这个团队认为由于内核和用户空间之间移动数据所采取的机制(如数据拷贝和上下文切换),内核正在阻碍实现良好可扩展的网络性能,所以他们完全抛弃内核,利用新的网卡NIC和CPU功能(如multiqueue),将设备驱动程序和网络堆栈直接移入应用程序,并将内核完全从IO路径中取出。
3. Arrakis:git
做法和mTCP类似,它不仅在应用数据上绕过了内核,它不仅对网络数据包进行内核屏蔽,对数据存储也进行了屏蔽。
4. Sandstorm:论文地址 比mTCP在层和API方面更深入一些,它保留了到客户端应用程序的POSIX套接字接口,尽管它们被重新编译链接到mTCP而不是网络的libc,它还实现了一个用户级堆栈,对网络代码进行特定应用调整,为Web和DNS服务器实现提供加速。
5. 国内的几个大的用户态协议栈
- DPDK-ANS,类似mTCP,他们和阿里走得比较近,已经开始商业运作了,但是开源不是很多:git传送
- f-stack,腾讯一个团队开发的用户态协议栈,使用了FreeBSD:git传送
四、其他解决方案
上面的分析我们可以看到,主要瓶颈就是内核,绕过内核就能够获更高的性能,安全性咋办呢,IX似乎更好一些,他们的项目中集成了一个dune的系统,这套系统类似于一个安全壳,也就是他们所言的dataplane operating system,dune这个项目是10年就开始做的,所以他们相当于是搞了一套结合运用。
我在跑这套项目的时候还注意到了另一套标准RDMA(Remote Direct Memory Access)远程直接数据存取,就是为了解决网络传输中服务器端数据处理的延迟而产生的。RDMA这种技术以前只能运行在专用网络下(例如超算平台),为了将这种技术用在以太网环境下,就逐步发展出了RoCE/iWarp两种协议。RoCE目前主要是由Mellonax主导(以色列一家专注高性能网络设备研发的公司),和TCP协议无关,性能更好。iWarp主要由Chelsio主导,下层会依赖TCP协议,性能和可扩性行都差一些,优点是考虑了对广域网的支持。目前来看RoCE比iWarp前景更好,实际使用也更广泛。对比DPDK,DPDK是Intel主导,提供了基于用户态的数据链路层的功能,可以在上面构建出基于用户态的网络栈。实际使用中一个显然的缺点是只有poll功能,没有陷入中断来减少对CPU的消耗。明显RDMA偏专用线路(需要专用网卡支持),DPDK则走通用路线(Intel自己就搞定了)。[3]