本文为作者原创,转载请注明出处(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. Windows下pycharm远程连接服务器调试-tensorflow无法加载问题

    最近打算在win系统下使用pycharm开发程序,并远程连接服务器调试程序,其中在import tensorflow时报错如图所示(在远程服务器中执行程序正常): 直观错误为: ImportError ...

  2. Java提高十七:TreeSet 深入分析

    前一篇我们分析了TreeMap,接下来我们分析TreeSet,比较有意思的地方是,似乎有Map和Set的地方,Set几乎都成了Map的一个马甲.此话怎讲呢?在前面一篇讨论HashMap和HashSet ...

  3. .net 系列:事件和委托

    在.net 的世界里,离不开委托和事件,其实理解透了后很简单,总结了一下分为5步:   1)定义委托   public delegate void RevicedEventHandler(object ...

  4. (译)学习JavaScript闭包

    原文地址:https://medium.freecodecamp.org/lets-learn-javascript-closures-66feb44f6a44   闭包是JavaScript中一个基 ...

  5. 弄明白python reduce 函数

    作者:Panda Fang 出处:http://www.cnblogs.com/lonkiss/p/understanding-python-reduce-function.html 原创文章,转载请 ...

  6. var a=function(){...}与function a(){...}的区别

    var a = function(){...}在js预加载时按变量处理,即预加载定义,不加载赋值. function a(){...}即加载定义,而且赋值. 例如:a(); //正常执行a()函数; ...

  7. .NET作品集:linux下的博客程序

    博客程序架构 本博客程序是博主11年的时候参考loachs小泥鳅博客内核开发的.net跨平台博客cms,距今已有6年多了,个人博客网站一直在用,虽然没有wordpress那么强大,但是当时在深究.ne ...

  8. mysql最佳优化经验

    今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数据库的性能,这并不只是DBA才需要担心的事,而这更是我们程序员需要去关注的事情.当我们去设计数据库表结构,对操作数据 ...

  9. 关于PHP 采集类

    伟大的筒子们,我们需要经常采集. 不知道大家每次采集的时候会不会烦躁,不用八爪鱼,不用PYTHON 是不是感到手无力,看到正则匹配每次匹配不对,一换采集内容就是头疼,重新拼写正则? 不要说是高手 ,就 ...

  10. 用echartsjs 实现动态绘制折线、柱状等图形,并实现多图联动效果

    echarts对于大数据处理后绘制折线图,柱形图等等的效果和速度都很好.下面我们介绍 怎么把封装的数据列表解析出来,动态绘图,并且实现鼠标联动效果引入js文件: <script type=&qu ...