本文为作者原创,转载请注明出处(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]

  发展出这么多协议和实现,根本原因在于网络硬件发展很快,而目前占据主导的TCP/IP协议仍然是为了适配当初低速网络环境设计的。关注了一下最近DPDK在学术界的走向,以及开始向底层网件发展了,相信不久就会出现成熟商用的通用型快速网络体系。
 
 
参考:
[1]https://mp.weixin.qq.com/s?__biz=MzA3ODgyNzcwMw==&mid=202113096&idx=1&sn=7ce616f596c529890dfd475ce8d31858&scene=4#wechat_redirect
[2]http://dpdk.org/browse/dpdk/tree/examples/
[3]http://blog.csdn.net/sdulibh/article/details/51829830

NFV、DPDK以及部分用户态协议研究的更多相关文章

  1. 用户态tcp协议栈调研

    一.各种用户态socket的对比 1.MTCP 简单介绍: 韩国高校的一个科研项目,在DPDK的2016年的技术开发者大会上有讲,所以intel将这个也放到了官方上,所以一般搜索DPDK的用户态的协议 ...

  2. [中英对照]User-Space Device Drivers in Linux: A First Look | 初识Linux用户态设备驱动程序

    如对Linux用户态驱动程序开发有兴趣,请阅读本文,否则请飘过. User-Space Device Drivers in Linux: A First Look | 初识Linux用户态设备驱动程序 ...

  3. C1000k 新思路:用户态 TCP/IP 协议栈

    现在的服务器支撑上百万个并发 TCP 连接已经不是新闻(余锋2010年的演讲,ideawu 的 iComet 开源项目,WhatsApp 做到了 2.5M).实现 C1000k 的常规做法是调整内核参 ...

  4. Linux操作系统学习_用户态与内核态之切换过程

    因为操作系统的很多操作会消耗系统的物理资源,例如创建一个新进程时,要做很多底层的细致工作,如分配物理内存,从父进程拷贝相关信息,拷贝设置页目录.页表等,这些操作显然不能随便让任何程序都可以做,于是就产 ...

  5. 在linux系统中实现各项监控的关键技术(2)--内核态与用户态进程之间的通信netlink

    Netlink 是一种在内核与用户应用间进行双向数据传输的非常好的方式,用户态应用使用标准的 socket API 就可以使用 netlink 提供的强大功能,内核态需要使用专门的内核 API 来使用 ...

  6. 用户态使用 glibc/backtrace 追踪函数调用堆栈定位段错误【转】

    转自:https://blog.csdn.net/gatieme/article/details/84189280 版权声明:本文为博主原创文章 && 转载请著名出处 @ http:/ ...

  7. 内核态与用户态通信 之 sockopt

    转自:http://blog.csdn.net/jk110333/article/details/8642261   用户态与内核态交互通信的方法不止一种,sockopt是比较方便的一个,写法也简单. ...

  8. 用户态处理arp、ndisc neighbour solication 报文

    问题背景: 想要协议栈给不是接口ip的报文,ipv4回复arp request,ipv6回复 ndisc solication. #include <stdio.h> //调用该函数成为一 ...

  9. Linux 内核态与用户态通信 netlink

    参考资料: https://blog.csdn.net/zqixiao_09/article/details/77131283 https://www.cnblogs.com/lopnor/p/615 ...

随机推荐

  1. KingView 6.53漏洞学习研究

    类别:堆溢出 描述:此漏洞存在于KingView6.53软件的HistorySvr.exe进程中,这个软件服务程序在TCP 777端口监听时收到一个超长请求,导致堆缓冲区溢出从而执行任何代码. 参考资 ...

  2. SpringMVC RequestMapping 详解

    SpringMVC RequestMapping 详解 RequestMapping这个注解在SpringMVC扮演着非常重要的角色,可以说是随处可见.它的知识点很简单.今天我们就一起学习Spring ...

  3. Python 学习之路3

    接下来把剩下的实验一起写上去 实验2 写一个学生类,属性有学号,姓名,成绩(三门),方法有输出,求平均成绩. 设计思路: 1.         先写一个学生类,并向里面写一个求平均值和输出信息的方法. ...

  4. ASP.NET异常处理机制

    try{ //获取并使用资源,可能出现异常}catch(DivideByZeroException de){}catch(ArithmeticException ae){}catch(Exceptio ...

  5. 鼠标相关操作(Cursor类及相关API)

    Cursor.visible:属性,显示或者隐藏鼠标.  Cursor.lockState = CursorLockMode.Locked:锁定鼠标到游戏窗口的中心. (CursorLockMode: ...

  6. Java 执行CMD/DOS

    最近在写一个自己的邮箱服务器里用到 监视及起/停 windows 中的服务,调查发现还是得用dos来做这些事情 说一下遭遇战的过程 首先是java里如何执行DOS命令,查到下记函数 Runtime.g ...

  7. python_day05(去爬登录的豆瓣)

    # 爬豆瓣需要用cookie# 需要注意隐藏的参数,即input 里面的默认的一些参数# 需要自己注册一个账户密码import urllib.requestimport http.cookiejarf ...

  8. Java开发步骤

    3.编辑Java源程序 使用纯文本编辑器,比如记事本notpad.exe:EditPlus.UltraEdit等专业的纯文本编辑器. Word不是纯文本编辑器. 需求:写一个Java程序,在控制台打印 ...

  9. vue.js权威指南 PDF

    链接:https://pan.baidu.com/s/1c2ItN6S 密码:ya8r

  10. PHP数组实际占用内存大小的分析

    一般来说,PHP数组的内存利用率只有 1/10, 也就是说,一个在C语言里面100M 内存的数组,在PHP里面就要1G.下面我们可以粗略的估算PHP数组占用内存的大小,首先我们测试1000个元素的整数 ...