Linux内核的TCP协议栈和内核旁路的选择?
【前言】最近在实习公司用到了solarflare的万兆网卡,用到了网卡的openonload技术还有TCPDirect模式代码的编写,其理论基础都是内核旁路。网上关于内核旁路技术的介绍基本就两篇,我结合solarflare的技术文档,总结一下。
原文地址(需要翻墙):https://blog.cloudflare.com/why-we-use-the-linux-kernels-tcp-stack/
转:最近的一篇文章提出了“我们为什么使用Linux内核的TCP协议栈”的问题,并在Hacker News引发了非常有意思的讨论。我的经验绝大部分来自于在这里和生产环境中成千的机器打交道,我可以试着从这个角度回答这个问题。
让我们从一个更宽泛的问题开始 – 到底什么才是运行一个操作系统的意义?如果你打算运行一个单独的应用,那使用一个包含几千万行代码的内核听起来就像一个负担。但实际上,我们绝大多数的人都决定要使用某种类型的操作系统,并且我们这么做主要有两个原因。首先,操作系统层带来了硬件的独立性和容易使用的API。有了这些我们可以专注于编写适用于任何机器的代码 – 而不只是我们目前所拥有的特定的硬件。其次,操作系统添加了一个时间分享的层。这让我们能同时运行多个应用。不管是一个额外的HTTP 服务器还是一次Bash会话,这个能在多个进程之间共享资源十分重要。所有被内核暴露出来的资源都可以在多个进程之间进行共享。
一个重要的问题,tcp/ip协议无法带来多CPU的线性加速。
一、用户空间网络
对于网络栈来说并没有什么不同。通过使用通用的操作系统网络协议栈我们拥有了运行多个网络应用的能力。然而如果我们为了运行一个用户空间的网络栈,将网络硬件专用于一个应用程序的话,这个能力就丢失了。通过要求将网卡仅为一个进程使用,你就失去了和你的服务器同时运行的能力另外一个应用,如一个SSH会话,的能力。
可能这听起来有点不可思议,但是这正是绝大多数的用户空间网络栈技术的目的。用来完整描述这个名词叫做“完全内核旁路(full kernel bypass)”。这想法是绕过内核,然后直接从用户空间的进程使用网络硬件。
在Linux的生态环境中,有一些已经存在的技术。不是所有的都是开源的:
PF_RING
Snabbswitch
DPDK
Netmap
我已经在之前的一篇文章讲过它们。所有的的这些技术都需要将网卡整个移交给一个单独的进程。换句话说:完全有可能编写你自己的网络协议栈,让他变得聪明,专注于高级的特性,并且针对性能进行优化。但是这会招来一个很大的开销 – 每一张网卡最多只能将它用于一个进程。
关于虚拟网卡(VF)这里有一个小小改变,但是我们不要在这里讨论它——它无法工作。我已经在“虚拟化方案”的那一段中讲到了它。
但即使有种种障碍,我也不能简单地否定内核旁路的好处。确实有很多人在运行自定义的网络协议栈,并且他们可能出于下面两个原因之一:
延迟
性能(更低的CPU消耗,更高的吞吐量)
延迟对于高率交易(high frequency tradin)来说至关重要。交易者能支付得起自定义的硬件,和各种复杂的私有网络栈。运行一个闭源的TCP协议栈会让我很不自在。
在CloudFlare的内核旁路
https://blog.cloudflare.com/kernel-bypass/
https://blog.csdn.net/wwh578867817/article/details/50139819
尽管这么说,在CloudFlare我们也的确使用内核绕行。我们是上面提到的第二种人,我们很在乎性能。更加明确的说,我们遭受着IRQ风暴的问题。Linux的网络栈一秒钟能处理的数据包是有限的。当达到上限的时候,所有的CPU都忙于接收数据包。在这种情形下,数据包要么被丢弃,要么会导致应用CPU匮乏( starve of CPU)。尽管在正常的情况下我们不用处理IRQ风暴,但是当我们是一次三层(OSI中的第三层)DDoS攻击的对象的时候就会成为问题。这是一种攻击目标被各种随意的不属于任何合法连接数据淹没的攻击 – 通常来说都是欺骗数据包(spoofed packets)。
在一些攻击中我们一台服务器会遭受一秒高达3Mpps的数据包。一个广泛适用的法则就是Linux的iptables能在一个不错的服务器上处理约1Mpps的数据包的同时,仍为应用留下足够多的CPU。这个数字还可以通过调优来提高。
对于这种规模的攻击来说Linux内核对于我们来说是不够的。我们必须找到解决方法。我们没有使用之前提到的“完全内核旁路”,相反的我们使用的是我们自称为的“部分内核旁路”。通过它内核仍然保留网卡的的拥有权,并且能让我们只在一个单独的“接收队列(Rx Queue)”上执行旁路。我们在SolarFlare的网卡上使用Solarflare的EFVI API。为了支持Intel的网卡,我们给Netmap添加了一个部分内核旁路的特性:这个在这篇文章里有讲到。通过这个技术我们可以将我们的抗DDoS iptable分担到一个十分快的用户进程。这让Linux不用再处理攻击的数据包,因此避免了IRQ风暴的问题。
二、一个完全的用户空间TCP协议栈如何呢?
我们的同事经常会问我:我们什么我们不用Solarflare的OpenOnload框架来运行我们的Nginx呢,使用十分快速的用户空间TCP?
是的,这会更快,但是没有证据这能产生什么实际上的不同。我们服务器绝大多数使用的CPU被用在了用户空间的Nginx进程而不是操作系统。CPU主要用在经常的Nginx的簿记和我们的Lua应用逻辑,而不是处理网络。我估计通过旁路我们能节省大约5%-10%的CPU,这(至少在目前看来)并不值当。但是对于量化交易的延时很重要。
其次,为了Nginx使用内核旁路会干扰我们平常使用的调试工具。我们的systemtap脚本会变得没有用。Linux的netstat统计会停止记录重要的事件,并且tcpdump不会再工作。然后我们的DDoS缓解栈来说也有一个问题。我们是iptables的重度用户,正如我们在这个BlackHat的演讲中讲到的。自定义的TCP协议栈是没有入”hashlimits”和”ipsets”这类东西的。
但是不只防火墙的特性。Linux的TCP协议栈有一些特别有用的非常重要的支持,如RFC4821,可以通过用sysctl的sys.net.ipv4.tcp_mtu_probing来设置。这种支持当一个用户在一个ICMP的黑洞后面来说是非常重要的。可以通过阅读这个文章来了解PMTU。
最后,每一个TCP协议栈都会有一些自己的问题和怪异模式。我们已经描述了三种Linux TCP栈中不是很显而易见的Linux怪异问题:
读缓冲中垃圾回收器闯入的问题
关于太多监听套接字的问题
一个套接字可写意味着什么
想像一下要在一个闭源或者年轻的TCP协议栈中要调试这种问题意味着什么。
三、结论
有两个问题:
第一,目前还没有稳定的开源的部分内核旁路技术。我们希望Netmap能抢占这个商机,并且我们在积极地通过我们自己的补丁来支持它。
第二,Linux TCP协议栈有很多重要的特性和优秀的调试能力。需要花费几年的的时间来能挑战这个丰富的生态系统。
鉴于这些原因,基于用户空间的网络是不大可能成为主流的。在实践中,我只能想象少数合理的应用需要用到内核旁路技术:
1、软件的交换机或者路由器。这里你想将网卡交由应用来处理,让它们来处理原始的数据包并且完全绕开内核。
2、专用的负载均衡器。类似的,如果该机器只用来做数据包的随机处理( packet shuffling ),那绕过内核就是合理的。
3、对于选定的高吞吐/低延迟的应用进行部分旁路。这就是在我们的DDoS缓解系统中用到的。不幸的是,我尚不知道有什么稳定且开源的TCP协议栈是适合这一类的。
4、对于普通用户来说,Linux的网络栈才是正确的选择。尽管这比起自己重写TCP协议栈来说不那么振奋人心,但是我们专注于理解Linux栈的性能并且修复其中问题。已经有一些正在进行的严肃的提议来改善这个年老优秀的Linux TCP协议栈。
5、量化交易高频、中低频交易可以使用。
Linux内核的TCP协议栈和内核旁路的选择?的更多相关文章
- CVE-2019-11477:Linux 内核中TCP协议栈整数溢出漏洞详细分析 代码卫士 今天
CVE-2019-11477:Linux 内核中TCP协议栈整数溢出漏洞详细分析 代码卫士 今天
- linux下TCP/IP及内核参数优化调优(转)
Linux下TCP/IP及内核参数优化有多种方式,参数配置得当可以大大提高系统的性能,也可以根据特定场景进行专门的优化,如TIME_WAIT过高,DDOS攻击等等. 如下配置是写在sysctl.con ...
- Linux内核中TCP SACK机制远程DoS预警通告
漏洞描述 2019年6月18日,RedHat官网发布报告:安全研究人员在Linux内核处理TCP SACK数据包模块中发现了三个漏洞,CVE编号为CVE-2019-11477.CVE-2019-114 ...
- Linux 升级内核开启 TCP BBR 有多大好处
前言 如果你有订阅一些科技新闻,应该会有看过内核在4.9当中加入了一个新的算法,来解决在有一定的丢包率的情况下的带宽稳定的问题,这个是谷歌为我们带来的干货,新的 TCP 拥塞控制算法 BBR (Bot ...
- TCP/IP及内核参数优化调优
Linux下TCP/IP及内核参数优化有多种方式,参数配置得当可以大大提高系统的性能,也可以根据特定场景进行专门的优化,如TIME_WAIT过高,DDOS攻击等等.如下配置是写在sysctl.conf ...
- TCP/IP及内核参数优化调优(转)
Linux下TCP/IP及内核参数优化有多种方式,参数配置得当可以大大提高系统的性能,也可以根据特定场景进行专门的优化,如TIME_WAIT过高,DDOS攻击等等.如下配置是写在sysctl.conf ...
- Linux内核Makefile文件(翻译自内核手册)
--译自Linux3.9.5 Kernel Makefiles(内核目录documention/kbuild/makefiles.txt) kbuild(kernel build) 内核编译器 Thi ...
- Linux中mod相关的命令 内核模块化 mod相关命令都是用来动态加载内核模块/驱动程序模块
Linux中mod相关的命令 内核模块化 mod相关命令都是用来动态加载内核模块/驱动程序模块 http://baike.baidu.com/link?url=lxiKxFvYm-UfJIxMjz ...
- Linux设备驱动工程师之路——内核链表的使用【转】
本文转载自:http://blog.csdn.net/forever_key/article/details/6798685 Linux设备驱动工程师之路——内核链表的使用 K-Style 转载请注明 ...
随机推荐
- java中== equal hashcode 比较的区别
== 基本数据类型是进行数值的比较 引用数据类型比较的是两对象的地址值 实际上都是进行直接值的比较 equal(Object) Object型参数,任何类型的实参都可以传入,只有实参是一个字符串且内容 ...
- 数理统计7:矩法估计(MM)、极大似然估计(MLE),定时截尾实验
在上一篇文章的最后,我们指出,参数估计是不可能穷尽讨论的,要想对各种各样的参数作出估计,就需要一定的参数估计方法.今天我们将讨论常用的点估计方法:矩估计.极大似然估计,它们各有优劣,但都很重要.由于本 ...
- A - A Supermarket (贪心, 并查集)
超市里有n个产品要卖,每个产品都有一个截至时间dx(从开始卖时算起),只有在这个截至时间之前才能卖出并且获得率润dy. 有多个产品,所有可以有不同的卖出顺序,每卖一个产品要占用1个单位的时间,问最多能 ...
- 1154 Vertex Coloring
题目前半略 Sample Input: 10 11 8 7 6 8 4 5 8 4 8 1 1 2 1 4 9 8 9 1 1 0 2 4 4 0 1 0 1 4 1 0 1 3 0 0 1 0 1 ...
- zjnu1730 PIRAMIDA(字符串,模拟)
Description Sample Input 6 JANJETINA 5 1 J 1 A 6 N 6 I 5 E Sample Output 1 0 2 1 1 题意:给你一个长度小于等于10^6 ...
- zjnu1707 TOPOVI (map+模拟)
Description Mirko is a huge fan of chess and programming, but typical chess soon became boring for h ...
- IntelliJ IDEA 运行java程序时出现“程序发生找不到或无法加载主类 cn.test1.test1”错误
在你程序不出现错误,而且你的编译器已经成功导入后 成功导入的样子 你可以重新打开一个项目 这就可以了^_^
- 洛谷 P6851 onu (贪心,模拟)
题意:C和D打牌,每张牌有花色和点数,小D刚开始的分数为\(v\),不管输还是赢,只要小D出了牌(花色必须相同),就能得到那张牌点数的分数,若是赢了(点数不小于D的牌),他可以另外加\(c\)分,输了 ...
- Socket 编程简介
Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯. 本章节我们为大家接收 Perl ...
- Pymongo 笔记
Pymongo 1.MongoDB概念 MongoDB是一种非关系型数据库(NoSQL),MongoDB数据存储于内存,内存不足则将热度低数据写回磁盘.存储的数据结构为文档.每个数据库包含若干集合(c ...