我们为什么使用Linux内核的TCP栈

栏目: 服务器 · 发布时间: 5年前

内容简介:最近,有一篇文章提出了一个非常有趣的问题,在CloudFlare工作的时候,我也一直在想这个问题。我的经验主要来自于和数千台生产机器打交道,我也会从这个角度来尝试回答这个问题。

本文是 Why we use the Linux kernel’s TCP stack 的翻译。

最近,有一篇文章提出了一个非常有趣的问题, 我们为什么使用 Linux 内核的TCP栈? 这在 Hacker News 上引发了非常有趣的讨论。

在CloudFlare工作的时候,我也一直在想这个问题。我的经验主要来自于和数千台生产机器打交道,我也会从这个角度来尝试回答这个问题。

我们为什么使用Linux内核的TCP栈
CC BY 2.0 图片 来自 John Vetterli

让我们从一个更加宽泛的问题开始——跑起来一个操作系统是为了啥?如果你仅仅打算运行一个应用程序,那么运行数百万行代码的内核听起来绝对是一个负担。

但,我们通常都决定跑一个操作系统,有两个原因。第一,操作系统层提供了硬件独立性,以及很容易使用的API。这样,我们就可以为任何机器写代码了——不仅仅是当前运行代码的这种机器。第二,操作系统提供了时分复用层。这让我们能同时运行多个程序。不管它是另一个http服务,还是仅仅是一个bash会话,这种不同进程共享资源的能力是非常重要的。所有由内核暴露出来的资源都是能够被多个进程共享的!

用户态网络

对于网络栈,这也没什么不同。运行通用操作系统的网络栈,我们能够运行多个网络程序。如果为了运行用户态网络栈,而让单个应用程序独享网卡硬件,那就会丢失这种能力。将一个网卡分配给另一个程序,那么很可能就没法同时与服务器进行ssh会话了。

这听起来很疯狂,但这正是很多用户态网络栈所建议的。通用术语叫“全内核旁路”(full kernel bypass)。即绕过内核,用户态进程直接使用网络硬件 。

我们为什么使用Linux内核的TCP栈
CC BY 2.0 图片 来自 Audiotecna Música

在Linux生态系统内,有好几种类似的技术。并不是所有的都是开源的:

我在 之前的博文 中提到过它们。这些技术都需要将整个网卡交给一个进程。换句话说,你完全可以写自己的网络栈,精心设计它,提供新特性,并优化性能。但这有一个巨大的成本——每个网卡只能被一个进程使用。

关于虚拟网卡(virtualized network cards,VIF),情况有一点点复杂,但是我们不做深入,它完全没用。我在 “虚拟化方法”一节 中谈到了这一点。

但是即使有这些障碍,我也不能忽视内核旁路的好处。许多人却是在运行自定义网络栈,主要有两个原因:

  • 延迟
  • 性能(更低的cpu消耗,更高的吞吐量)

延迟对高频交易人员很重要。他们可以负担的起定制硬件、流行的专有网络栈。运行一个闭源的TCP栈会让我感觉很不舒服。

CloudFlare的内核旁路

尽管如此,在CloudFlare,我们仍然使用内核旁路技术。我们术语第二种类型——我们关注性能。更确切的说,我们遭受了IRQ风暴。Linux网络栈每秒处理的包个数有限,当到达这个限制的时候,所有CPU都忙着接受数据包。在这种情况下,要么丢弃一些包,要么应用程序没有足够的CPU资源。虽然在正常情况下我们不需要应对IRQ风暴,但当我们成为L3(OSI模型中的第三层)攻击目标时,这种情况确实会发生。这是一种攻击类型,目标被无效的TCP包淹没,即这些TCP包不属于任何有效的TCP连接。

我们为什么使用Linux内核的TCP栈
CC BY-SA 2.0 图片 来自 Howard Lake

在有些网络攻击中,每个服务器被每秒多达三百万个数据包淹没。一般的经验法则是,Linux iptables在一个不错的处理器上每秒能处理一百万个包,同时仍然有足够的CPU资源给应用程序。这个极限也可以通过适当的调优来增加。

在这种规模的攻击下,Linux 内核是不够的。我们必须解决这个问题。我们不使用之前提到的“完全内核旁路”,而是运行我们所称的“部分内核旁路”。这样内核就保留了网卡的所有权,我们也可以仅在一个“RX队列”上执行内核旁路。我们在 Solarflare 网卡上,使用Solarflare的EFVI API。为了支持Intel网卡,我们给Netmap添加了部分内核旁路的支持:这在 这篇文章 有说明。有了这种技术,我们可以将反DDos的iptables规则卸载到一个非常快的用户态进程。使Linux内核免于处理攻击包,避免IRQ风暴。

那么,纯用户空间网络栈呢?

我的同事经常问我: 为什么我们不直接在Solarflare 的 OpenOnload 框架上运行NGINX,使用超级快的用户态TCP呢?

是的,那样会很快,但没有证据表明它会产生很多实际影响。大部分CPU都用于用户态的NGINX进程,而不是操作系统内核。CPU主要用于通常的NGINX逻辑和 Lua 应用程序逻辑,而不是网络处理。我估计使用内核旁路我们可以节省大约5-10%的CPU,这(目前)不值得尝试。

我们为什么使用Linux内核的TCP栈
CC BY 2.0 图片 来自 Charlie

其次,为NGINX使用内核旁路会干扰我们常用的调试工具。我们的 systemtap脚本 将变得完全没用。Linux netstat也不再记录关键事件,tcpdump也不能使用。

然后是如何缓解DDoS攻击。正如我在这个 BlackHat演讲 中所说的,我们是iptables的忠实用户。自定义TCP栈没有” hashlimits “和” ipset “之类的东西。

但不仅是防火墙的功能。Linux TCP栈对诸如 RFC4821sys.net.ipv4.tcp_mtu_probe 这样的sysctl配置等提供了一些非常有用的支持。当用户位于ICMP黑洞的后面时,对这一点的支持是至关重要的。阅读 关于PMTU的博文 了解更多。

最后,每个TCP栈都有自己的缺陷和妥协。我们已经发现了Linux TCP栈中的三个不明显的妥协:

想象一下,在一个闭源的,或者新的(或者新的且闭源的)TCP栈中调试这些问题。

结论

有两点:第一,目前还没有一个稳定的、开源的部分内核旁路技术。我们希望Netmap能够占领这个市场,我们也在 用自己的补丁来支持它 。第二,Linux TCP栈有很多关键特性以及非常好的调试功能。与Linux TCP生态系统竞争需要数年时间。

基于这些原因,用户态网络不太可能成为主流。在实践中,我只能想到几个合理的内核旁路技术应用:

  • 软件交换机或者路由器。你希望将网卡交给应用程序,让应用程序处理原始数据包,并完全跳过内核。
  • 专用负载均衡。类似的,如果机器只是分发数据包,那么跳过内核是有意义的。
  • 将高吞吐的、低延迟的应用程序部分旁路。这是我们用于应对DDoS攻击的设置。然而,我不知道有没有一个稳定的、开源的TCP栈适合这个场景。

对于一般用户来说,Linux网路栈是正确的选择。尽管它没有重写TCP堆栈那么令人兴奋,但是我们应该集中精力 理解Linux堆栈性能 并修复它的问题。有 一些重要的举措 也正在推进,以改进旧的Linux TCP堆栈的性能。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

图解TCP/IP : 第5版

图解TCP/IP : 第5版

[日]竹下隆史、[日]村山公保、[日]荒井透、[日]苅田幸雄 / 乌尼日其其格 / 人民邮电出版社 / 2013-7-1 / 69.00元

这是一本图文并茂的网络管理技术书籍,旨在让广大读者理解TCP/IP的基本知识、掌握TCP/IP的基本技能。 书中讲解了网络基础知识、TCP/IP基础知识、数据链路、IP协议、IP协议相关技术、TCP与UDP、路由协议、应用协议、网络安全等内容,引导读者了解和掌握TCP/IP,营造一个安全的、使用放心的网络环境。 本书适合计算机网络的开发、管理人员阅读,也可作为大专院校相关专业的教学参考......一起来看看 《图解TCP/IP : 第5版》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

在线进制转换器
在线进制转换器

各进制数互转换器

html转js在线工具
html转js在线工具

html转js在线工具