【前言】最近在实习公司用到了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协议栈和内核旁路的选择?的更多相关文章

  1. CVE-2019-11477:Linux 内核中TCP协议栈整数溢出漏洞详细分析 代码卫士 今天

    CVE-2019-11477:Linux 内核中TCP协议栈整数溢出漏洞详细分析 代码卫士 今天

  2. linux下TCP/IP及内核参数优化调优(转)

    Linux下TCP/IP及内核参数优化有多种方式,参数配置得当可以大大提高系统的性能,也可以根据特定场景进行专门的优化,如TIME_WAIT过高,DDOS攻击等等. 如下配置是写在sysctl.con ...

  3. Linux内核中TCP SACK机制远程DoS预警通告

    漏洞描述 2019年6月18日,RedHat官网发布报告:安全研究人员在Linux内核处理TCP SACK数据包模块中发现了三个漏洞,CVE编号为CVE-2019-11477.CVE-2019-114 ...

  4. Linux 升级内核开启 TCP BBR 有多大好处

    前言 如果你有订阅一些科技新闻,应该会有看过内核在4.9当中加入了一个新的算法,来解决在有一定的丢包率的情况下的带宽稳定的问题,这个是谷歌为我们带来的干货,新的 TCP 拥塞控制算法 BBR (Bot ...

  5. TCP/IP及内核参数优化调优

    Linux下TCP/IP及内核参数优化有多种方式,参数配置得当可以大大提高系统的性能,也可以根据特定场景进行专门的优化,如TIME_WAIT过高,DDOS攻击等等.如下配置是写在sysctl.conf ...

  6. TCP/IP及内核参数优化调优(转)

    Linux下TCP/IP及内核参数优化有多种方式,参数配置得当可以大大提高系统的性能,也可以根据特定场景进行专门的优化,如TIME_WAIT过高,DDOS攻击等等.如下配置是写在sysctl.conf ...

  7. Linux内核Makefile文件(翻译自内核手册)

    --译自Linux3.9.5 Kernel Makefiles(内核目录documention/kbuild/makefiles.txt) kbuild(kernel build) 内核编译器 Thi ...

  8. Linux中mod相关的命令 内核模块化 mod相关命令都是用来动态加载内核模块/驱动程序模块

    Linux中mod相关的命令 内核模块化   mod相关命令都是用来动态加载内核模块/驱动程序模块 http://baike.baidu.com/link?url=lxiKxFvYm-UfJIxMjz ...

  9. Linux设备驱动工程师之路——内核链表的使用【转】

    本文转载自:http://blog.csdn.net/forever_key/article/details/6798685 Linux设备驱动工程师之路——内核链表的使用 K-Style 转载请注明 ...

随机推荐

  1. 理解了这三点,才敢说自己会写Python代码

    某同学应聘Python岗位被录用.上班第一天,Leader吩咐他写一个获取次日日期信息的函数.该同学信心满满地写下了这样一段代码, 然后就没有然后了. import time def get_next ...

  2. Inceptor常用SQL

    1.创建数据库 建一个数据库exchange_platform. DROP DATABASE IF EXISTS exchange_platform CASCADE; CREATE DATABASE ...

  3. Codeforces Global Round 9 C. Element Extermination

    题目链接:https://codeforces.com/contest/1375/problem/C 题意 给出一个大小为 $n$ 的排列 $a$,如果 $a_i < a_{i+1}$,则可以选 ...

  4. HttpServletResponse的学习

    关于Response对象的一些方法和属性可以查看官方文档:https://javaee.github.io/javaee-spec/javadocs/ 比如里面定义了许多常量: 这些都是服务器向浏览器 ...

  5. 【uva 11134】Fabled Rooks(算法效率--问题分解+贪心)

    题意:要求在一个N*N的棋盘上放N个车,使得它们所在的行和列均不同,而且分别处于第 i 个矩形中. 解法:问题分解+贪心. 由于行.列不相关,所以可以先把行和列均不同的问题分解为2个"在区间 ...

  6. NCD 2019 H. Mr. Hamra and his quantum particles

    题意:给你n个数,有m次操作,每次使得两个数相连接,询问q次,问某两个数是否连接在一起. 题解:这其实是一道并查集的裸题,这里就不再多说了,写个路径压缩的find函数即可. 代码: #include ...

  7. 在Ubuntu虚拟机上搭建青岛OJ

    源码地址为:https://github.com/QingdaoU/OnlineJudge 可参考的文档为:https://github.com/QingdaoU/OnlineJudgeDeploy/ ...

  8. Leetcode(23)-合并K个排序链表

    合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂度. 示例: 输入: [   1->4->5,   1->3->4,   2->6 ] 输出: 1-&g ...

  9. 使用 js 实现一个简易版的 drag & drop 库

    使用 js 实现一个简易版的 drag & drop 库 具有挑战性的前端面试题 H5 DnD js refs https://www.infoq.cn/article/0NUjpxGrqRX ...

  10. TDD & Unit testing

    TDD & Unit testing TDD jest https://github.com/facebook/jest https://facebook.github.io/jest/zh- ...