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]
NFV、DPDK以及部分用户态协议研究的更多相关文章
- 用户态tcp协议栈调研
一.各种用户态socket的对比 1.MTCP 简单介绍: 韩国高校的一个科研项目,在DPDK的2016年的技术开发者大会上有讲,所以intel将这个也放到了官方上,所以一般搜索DPDK的用户态的协议 ...
- [中英对照]User-Space Device Drivers in Linux: A First Look | 初识Linux用户态设备驱动程序
如对Linux用户态驱动程序开发有兴趣,请阅读本文,否则请飘过. User-Space Device Drivers in Linux: A First Look | 初识Linux用户态设备驱动程序 ...
- C1000k 新思路:用户态 TCP/IP 协议栈
现在的服务器支撑上百万个并发 TCP 连接已经不是新闻(余锋2010年的演讲,ideawu 的 iComet 开源项目,WhatsApp 做到了 2.5M).实现 C1000k 的常规做法是调整内核参 ...
- Linux操作系统学习_用户态与内核态之切换过程
因为操作系统的很多操作会消耗系统的物理资源,例如创建一个新进程时,要做很多底层的细致工作,如分配物理内存,从父进程拷贝相关信息,拷贝设置页目录.页表等,这些操作显然不能随便让任何程序都可以做,于是就产 ...
- 在linux系统中实现各项监控的关键技术(2)--内核态与用户态进程之间的通信netlink
Netlink 是一种在内核与用户应用间进行双向数据传输的非常好的方式,用户态应用使用标准的 socket API 就可以使用 netlink 提供的强大功能,内核态需要使用专门的内核 API 来使用 ...
- 用户态使用 glibc/backtrace 追踪函数调用堆栈定位段错误【转】
转自:https://blog.csdn.net/gatieme/article/details/84189280 版权声明:本文为博主原创文章 && 转载请著名出处 @ http:/ ...
- 内核态与用户态通信 之 sockopt
转自:http://blog.csdn.net/jk110333/article/details/8642261 用户态与内核态交互通信的方法不止一种,sockopt是比较方便的一个,写法也简单. ...
- 用户态处理arp、ndisc neighbour solication 报文
问题背景: 想要协议栈给不是接口ip的报文,ipv4回复arp request,ipv6回复 ndisc solication. #include <stdio.h> //调用该函数成为一 ...
- Linux 内核态与用户态通信 netlink
参考资料: https://blog.csdn.net/zqixiao_09/article/details/77131283 https://www.cnblogs.com/lopnor/p/615 ...
随机推荐
- pyqt5实现打开子窗口
# -*- coding: utf-8 -*- import sys from PyQt5.QtWidgets import * from PyQt5.QtCore import * class Fi ...
- Vuex非常适合新手的教程,保教不会!
本讲解基于Vue-cli(脚手架)搭建的项目. Vuex 数据状态管理工具,整个流程类似依赖注入,相当于预先定义,倒推.(个人理解) 1. 安装vuex 命令行输入 npm install vuex ...
- springboot-mybatis 批量insert
springboot mybatis 批量insert 操作 直接上代码: 1.首先要在pom.xml中导入包: 略...... 2.springboot mybatis配置: package com ...
- StringUtils工具类常用方法汇总1(判空、转换、移除、替换、反转)
Apache commons lang3包下的StringUtils工具类中封装了一些字符串操作的方法,非常实用,使用起来也非常方便.最近自己也经常在项目中使用到了里面的一些方法,在这里将常用的方 ...
- Servlet,JSP 中的中文乱码问题以及解决方案
问题描述: 在Servlet,JSP 传递数据中,英文无影响,而中文有时候就会出现乱码. 解决方案: 相同的编码: 同一个项目中的每个文件应当设置和保存相同的编码方式,如: html中 <met ...
- Tomcat 日志分割
一.前言 随着每天业务的增长,Tomcat 的catalina.out日志 变得越来越大,占用磁盘空间不说.要查看某个时候的日志的时候,庞大的日志让你顿时无从下手,所以日志的切割的变得刻不容缓.而且, ...
- 51Nod 2006 飞行员配对(二分图最大匹配)
链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=2006 思路: 二分匹配 注意n m的关系 代码: #include ...
- POJ 3923 HDU 2487 Ugly Windows 简单计算
Ugly Windows Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tot ...
- eclipse中将本地项目上传到svn库
转载文章:http://blog.csdn.net/singit/article/details/48972197
- 组件嵌套时报:Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.
在组件嵌套的过程中,报了一个错误: 这里报错的原因是:vue的组件(模板)只能有一个根节点,即.vue文件中的<template>标签下只能有一个子元素. 因此,建议大家在写.vue组件的 ...