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 转载请注明 ...
随机推荐
- docker部署 springboot 多模块项目+vue
之前学习了docker,今天就来试试将这个项目打包成docker镜像并通过运行一个镜像来运行项目.这里使用的项目是el-admin.是一个开源的springboot后端管理框架(前端vue),有兴趣的 ...
- 矩阵树定理(Kirchhoff || Laplace)初探——Part 1(无向图计数)
必备知识: 高斯消元,图论基本知识(好像就这...(雾)) 这里是无向图部分,请不要走错场... 定义 我们将邻接矩阵定义为矩阵\(A(u,v)\),我想邻接矩阵就不用再多说了: 我们将每个点的度数矩 ...
- cf 1305 E. Kuroni and the Score Distribution
题目传送门:E. Kuroni and the Score Distribution 题目大意:给n和m,输出n个数,这些数里必须要有m对a[i]+a[j]==a[k] ( i < j < ...
- 【noi 2.2_8758】2的幂次方表示(递归)
题意:将正整数N用2的幂次方表示(彻底分解至2(0),2). 解法:将层次间和每层的操作理清楚,母问题分成子问题就简单了.但说得容易,操作没那么容易,我就打得挺纠结的......下面附上2个代码,都借 ...
- servlet相关知识点
一.servlet的生命周期 Servlet(Sever Applet),全称是Java Servlet,是用java编写的服务器程序.Servlet是指任何实现了这个Servlet接口的类. ser ...
- codeforces 1028C Rectangles【思维】
题目:戳这里 题意:有n个矩阵,求一个点(保证存在)至少在n-1个点内. 解题思路:因为矩阵与坐标轴平行,所以我们画图可以发现如果存在点满足条件,则这些点中一定有一个是矩阵的顶点.我们可以把所有顶点的 ...
- Netty(三)基于Bio和Netty 的简易版Tomcat
参考代码: https://github.com/FLGBetter/tomcat-rpc-demo
- CSS clip-path in action
CSS clip-path in action <!DOCTYPE html> <html lang="en"> <head> <meta ...
- LeetCode & list cycle
LeetCode & list cycle 链表是否存在环检测 singly-linked list 单链表 "use strict"; /** * * @author x ...
- Top 10 JavaScript errors
Top 10 JavaScript errors javascript errors https://rollbar.com/blog/tags/top-errors https://rollbar. ...