💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# 一千万个并发连接的秘密-内核是问题,而不是解决方案 > 原文: [http://highscalability.com/blog/2013/5/13/the-secret-to-10-million-concurrent-connections-the-kernel-i.html](http://highscalability.com/blog/2013/5/13/the-secret-to-10-million-concurrent-connections-the-kernel-i.html) <iframe align="right" allowfullscreen="" frameborder="0" height="188" src="http://www.youtube.com/embed/73XNtI0w7jA" width="250"></iframe> 现在我们遇到了 [C10K 并发连接问题](http://www.kegel.com/c10k.html) ,我们如何升级并支持 1000 万个并发连接? 你说不可能。 不,目前,系统正在使用可能不熟悉的根本技术提供 1000 万个并发连接。 要了解其操作方法,我们求助于 Errata Security 的首席执行官 [Robert Graham](https://twitter.com/ErrataRob) ,以及他在 [上的精彩演讲 Shmoocon 2013](https://www.shmoocon.org/) 被称为 [C10M 大规模防御互联网](http://www.youtube.com/watch?v=73XNtI0w7jA#!) 。 罗伯特有一个绝妙的方式来解决我从未听说过的问题。 他从一些历史开始,讲述了最初不是将 Unix 设计为通用服务器操作系统,而是将其设计为电话网络的控制系统。 电话网络实际上是在传输数据,因此控制平面和数据平面之间存在清晰的分隔。 **问题是我们现在将 Unix 服务器用作数据平面**的一部分,我们根本不应该这样做。 如果我们要设计一个内核来为每个服务器处理一个应用程序,那么它的设计将与多用户内核的设计大不相同。 这就是为什么他说关键是要理解: * 内核不是解决方案。 **内核是问题**。 表示: * **不要让内核完成所有繁重的工作**。 将数据包处理,内存管理和处理器调度从内核中移出,然后将其放入应用程序中,从而可以高效地完成它。 让 Linux 处理控制平面,让应用程序处理数据平面。 结果将是一个系统可以处理 1000 万个并发连接,其中 200 个时钟周期用于数据包处理,而 1400 个时钟周期用于应用程序逻辑。 由于主存储器访问需要 300 个时钟周期,因此设计的关键在于最大程度地减少代码和缓存丢失。 使用面向 **数据平面的系统** ,您每秒可以处理 1000 万个数据包。 使用面向控制平面的系统,您每秒只能获得一百万个数据包。 如果这看起来很极端,请记住一句老话: **可伸缩性是专业化** 。 要做到出色,就不能将性能外包给操作系统。 你必须自己做。 现在,让我们学习 Robert 如何创建一个能够处理 1000 万个并发连接的系统... ## C10K 问题-过去十年 十年前,工程师解决了 C10K 可伸缩性问题,该问题阻止服务器处理 10,000 多个并发连接。 通过修复操作系统内核并从线程服务器(如 Apache)移至事件驱动的服务器(如 Nginx 和 Node),解决了该问题。 随着人们从 Apache 转移到可伸缩服务器,此过程已花费了十年的时间。 在过去的几年中,我们看到了可扩展服务器的更快采用。 ### Apache 问题 * Apache 问题是连接越多,性能越差。 * 关键见解: **性能和可伸缩性或正交概念** 。 他们不是同一回事。 人们谈论规模时,通常是在谈论绩效,但是规模和绩效之间是有区别的。 正如我们将在 Apache 中看到的那样。 * 对于持续几秒钟的短期连接(例如快速交易)来说,如果您要执行 1000 TPS,则与服务器的并发连接数只有 1000。 * 将交易时间更改为 10 秒,现在以 1000 TPS 的速度打开了 1 万个连接。 尽管 Apache 的性能下降了很多,但这使您容易受到 DoS 攻击。 只需进行大量下载,Apache 就会崩溃。 * 如果每秒处理 5,000 个连接,并且要处理 10K,该怎么办? 假设您升级硬件并将处理器速度提高了一倍。 怎么了? 您可以获得双倍的性能,但规模却没有双倍。 规模只能达到每秒 6K 个连接。 如果您继续加倍,也会发生同样的事情。 性能提高了 16 倍,但您仍未达到 1 万个连接。 性能与可伸缩性不同。 * 问题是 Apache 会派生一个 CGI 进程,然后将其杀死。 这没有规模。 * 为什么? 由于内核中使用 O(n ^ 2)算法,服务器无法处理 10K 并发连接。 * 内核中的两个基本问题: * 连接=线程/进程。 当一个数据包进入时,它将遍历内核中的所有 10K 进程,以确定哪个线程应该处理该数据包 * 连接=选择/轮询(单线程)。 同样的可扩展性问题。 每个数据包都必须经过一个套接字列表。 * 解决方案:修复内核以在恒定时间内进行查找 * 现在,无论线程数量如何,线程都会进行恒定时间上下文切换。 * 引入了新的可扩展 epoll()/ IOCompletionPort 恒定时间套接字查找。 * 线程调度仍无法扩展,因此服务器使用带有套接字的 epoll 进行扩展,从而导致 Node 和 Nginx 中体现了异步编程模型。 这将软件转移到不同的性能图表。 即使在服务器速度较慢的情况下添加更多连接,性能也不会下降。 连接数为 10K 时,笔记本电脑甚至比 16 核心服务器还要快。 ## C10M 问题-下一个十年 在不久的将来,服务器将需要处理数百万个并发连接。 使用 IPV6,来自每台服务器的潜在连接数达到数百万,因此我们需要进入下一个可伸缩性级别。 * 需要此类可伸缩性的应用程序示例:IDS / IPS,因为它们连接到服务器主干。 其他示例:DNS 根服务器,TOR 节点,Internet 的 Nmap,视频流,银行业务,运营商 NAT,Voip PBX,负载均衡器,Web 缓存,防火墙,电子邮件接收,垃圾邮件过滤。 * 通常,看到 Internet 规模问题的人是设备而不是服务器,因为他们出售的是硬件和软件。 您购买设备并将其插入数据中心。 这些设备可能包含英特尔主板或网络处理器以及用于加密,数据包检查等的专用芯片。 * 截至 2013 年 2 月,Newegg 的 X86 价格为$ 5K(40gpbs,32 核,256gigs RAM)。 服务器可以执行超过 10K 的连接。 如果不能,那是因为您在软件方面做出了错误的选择。 问题不在于底层硬件。 该硬件可以轻松扩展到 1000 万个并发连接。 ### 10M 并发连接挑战的含义是: 1. 1000 万个并发连接 2. 1 百万个连接/秒-大约 10 秒的持续速率 3. 10 吉比特/秒的连接-快速连接到 Internet。 4. 1000 万个数据包/秒-期望当前的服务器每秒处理 5 万个数据包,这将达到一个更高的水平。 过去服务器每秒能够处理 100K 次中断,每个数据包都会引起中断。 5. 10 微秒延迟-可伸缩服务器可能会处理规模,但延迟会增加。 6. 10 微秒抖动-限制最大延迟 7. 10 个一致的 CPU 内核-软件应扩展到更大数量的内核。 通常,软件只能轻松扩展到四个内核。 服务器可以扩展到更多的内核,因此需要重写软件以支持更大的内核计算机。 ### 我们已经学习了 Unix 非网络编程 * 一代程序员已经通过阅读 W. Richard Stevens 的 Unix Networking Programming 学习了网络编程。 问题在于这本书是关于 Unix 的,而不仅仅是网络编程。 它告诉您让 Unix 承担所有繁重的工作,而您只需要在 Unix 之上编写一个小型服务器即可。 但是内核无法扩展。 解决方案是移出内核,自己做所有繁重的工作。 * 这种影响的一个例子是考虑每个连接模型的 Apache 线程。 这意味着线程调度程序根据到达的数据确定下一步要调用的 read()。 **您正在使用线程调度系统作为数据包调度系统** 。 (我真的很喜欢这个,以前从未想过)。 * Nginx 所说的它不使用线程调度作为数据包调度程序。 自己安排数据包。 使用 select 查找套接字,我们知道它有数据,因此我们可以立即读取它并且不会阻塞,然后处理该数据。 * 课程:**让 Unix 处理网络堆栈,但是从那时起,您将处理**上的所有内容。 ### 您如何编写可扩展的软件? 如何更改软件以使其可扩展? 关于硬件可以处理多少的很多经验法则都是错误的。 我们需要知道实际的性能能力。 要进入下一个级别,我们需要解决的问题是: 1. 包可扩展性 2. 多核可扩展性 3. 内存可扩展性 ### 数据包扩展-编写自己的自定义驱动程序以绕过堆栈 * 数据包的问题是它们通过 Unix 内核。 网络堆栈复杂且缓慢。 数据包到您的应用程序的路径需要更直接。 不要让操作系统处理数据包。 * 实现此目的的方法是编写自己的驱动程序。 驱动程序所做的只是将数据包发送到您的应用程序,而不是通过堆栈发送。 您可以找到驱动程序:PF_RING,Netmap,Intel DPDK(数据平面开发套件)。 英特尔是封闭源代码,但周围有很多支持。 * 多快? 英特尔有一个基准,该基准在相当轻巧的服务器上每秒处理 8000 万个数据包(每个数据包 200 个时钟周期)。 这也是通过用户模式。 数据包一直向上进入用户模式,然后再次下降出去。 当 UDP 数据包恢复到用户模式并再次输出时,Linux 每秒处理的数据包不超过一百万。 性能是 Linux 客户驱动程序的 80-1。 * 对于每秒 1000 万个数据包的目标,如果使用 200 个时钟周期来获取离开 1400 个时钟周期以像 DNS / IDS 那样实现功能的数据包。 * 使用 PF_RING 可以获取原始数据包,因此必须执行 TCP 堆栈。 人们在做用户模式栈。 对于英特尔,有一个可用的 TCP 堆栈可提供真正可扩展的性能。 ### 多核可扩展性 多核可扩展性与多线程可扩展性不同。 我们都对处理器的想法并不熟悉,但是越来越多。 大多数代码无法扩展到 4 个内核以上。 随着我们添加更多内核,不仅性能会下降,而且添加更多内核会越来越慢。 那是因为软件写得不好。 我们需要软件,因为我们添加了更多的内核以几乎线性地扩展。 希望随着我们添加更多核心而变得更快。 #### 多线程编码不是多核编码 * 多线程: * 每个 CPU 内核有多个线程 * 锁定以协调线程(通过系统调用完成) * 每个线程有不同的任务 * 多核: * 每个 CPU 内核一个线程 * 当两个线程/内核访问相同的数据时,它们将无法停止并互相等待 * 所有线程属于同一任务 * 我们的问题是如何在多个内核之间分布应用程序。 * Unix 中的锁是在内核中实现的。 使用锁的 4 个核心发生的事情是,大多数软件开始等待其他线程放弃锁。 因此,内核开始消耗更多的性能,而不是拥有更多 CPU 所获得的性能。 * 我们需要的是一种比起停车灯控制的交叉路口,更像是高速公路的建筑。 我们不想等待每个人按照自己的步调以尽可能少的开销继续前进。 * 解决方案: * 保持每个核心的数据结构。 然后在聚合时读取所有计数器。 * 原子学。 可以从 C 调用的 CPU 支持的指令。保证是原子的,永不冲突。 昂贵,所以不想用所有的东西。 * 无锁数据结构。 永不停止并等待彼此的线程可以访问。 不要自己做。 跨不同的架构工作非常复杂。 * 线程模型。 流水线与工作线程模型。 问题不只是同步,而是线程的架构方式。 * 处理器亲和力。 告诉操作系统使用前两个内核。 然后设置线程在哪些内核上运行的位置。 您也可以对中断执行相同的操作。 因此,您拥有这些 CPU,而 Linux 没有。 ## 内存可扩展性 * 问题是,如果您有 20gig 的 RAM,并且假设每个连接使用 2k,那么如果您只有 20meg 的 L3 缓存,则这些数据都不会在缓存中。 进入主内存需要 300 个时钟周期,这时 CPU 无法执行任何操作。 * 考虑每个数据包 1400 个时钟周期的变化。 请记住 200 个时钟/每包的开销。 每个数据包只有 4 个高速缓存未命中,这是一个问题。 * 并置数据 * 不要通过指针在整个内存上写数据。 每次跟随指针将导致高速缓存未命中:[哈希指针]-> [任务控制块]-> [套接字]-> [应用程序]。 那是四个缓存未命中。 * 将所有数据保存在一块内存中:[TCB | 插座 应用]。 通过预分配所有块来保留内存。 这样可以将缓存未命中次数从 4 个减少到 1 个。 * 分页 * 用于 32gigs 的分页表需要 64MB 的分页表,该页面不适合缓存。 因此,您有两个未命中的缓存,一个是针对分页表的缓存,另一个是其指向的缓存。 对于可扩展软件,这是我们不能忽略的细节。 * 解决方案:压缩数据; 使用高速缓存有效的结构,而不是具有大量内存访问权限的二进制搜索树 * NUMA 体系结构使主存储器访问时间加倍。 内存可能不在本地套接字上,但在另一个套接字上。 * 内存池 * 启动时一次预分配所有内存。 * 在每个对象,每个线程和每个套接字的基础上分配。 * 超线程 * 网络处理器每个处理器最多可以运行 4 个线程,英特尔只有 2 个。 * 这样可以掩盖例如内存访问的延迟,因为当一个线程等待另一个线程全速运行时。 * 大页面 * 减小页表大小。 从一开始就保留内存,然后由应用程序管理内存。 ### 摘要 * 没什么 * 问题:通过内核无法正常运行。 * 解决方案:使用您自己的驱动程序将适配器从操作系统中取出,并自行管理它们 * CPU * 问题:如果您使用传统的内核方法来协调应用程序,则效果不佳。 * 解决方案:为 Linux 提供前两个 CPU,然后您的应用程序将管理其余的 CPU。 在您不允许的 CPU 上不会发生中断。 * 内存 * 问题:要格外小心,以使其正常工作。 * 解决方案:在系统启动时,以您管理的大页面分配大部分内存。 控制平面留给 Linux 使用,对于数据平面则什么也没有。 数据平面以应用程序代码运行。 它从不与内核交互。 没有线程调度,没有系统调用,没有中断,什么都没有。 但是,您所拥有的是可以在 Linux 上正常运行的代码,您可以对其进行正常调试,这不是您需要定制工程师使用的怪异硬件系统。 通过熟悉的编程和开发环境,您可以获得数据平面所期望的自定义​​硬件的性能。 ## 相关文章 * 阅读 [Hacker News](https://news.ycombinator.com/item?id=5699552) 或 [Reddit](http://www.reddit.com/r/programming/comments/1e90q7/the_secret_to_10_million_concurrent_connections/) , [Hacker News Dos](https://news.ycombinator.com/item?id=7697483) * [是时候摆脱云中的 Linux OS 模型了吗?](http://highscalability.com/blog/2012/1/19/is-it-time-to-get-rid-of-the-linux-os-model-in-the-cloud.html) * [机器虚拟机+云 API-从头开始重写云](http://highscalability.com/blog/2010/10/21/machine-vm-cloud-api-rewriting-the-cloud-from-scratch.html) * [Exokernel](http://en.wikipedia.org/wiki/Exokernel) * [关于 C10M 的博客](http://c10m.robertgraham.com/) * [多核缩放:它不是多线程的](http://erratasec.blogspot.com/search/label/Shmoocon2013) ,具有良好的注释功能。 * [英特尔®DPDK:数据平面开发套件](http://dpdk.org/) 瓶颈的分解令人印象深刻,阅读这种正确的东西令人耳目一新。 现在我想扮演魔鬼的拥护者(主要是因为我完全同意这个家伙)。 提出的解决方案听起来像是定制的特定于硬件的解决方案,听起来就像是回到过去,那时您不能只是将一些相当随机的硬件放在一起,将 linux 打在上面然后继续前进……这将是对此的最大反对, 人们担心电器/供应商/驾驶员被锁住,这是一种理性的恐惧。 有什么计划使外行可以使用这些非常正确的体系结构实践。 需要某种 API,因此各个硬件堆栈都可以对其进行编码,并且此 API 一定不能是重量级的抽象。 这是一个艰巨的挑战。 最好的是,C10M 运动很幸运,如果我能在未来几年的某个时间里将一个可运行 C10M 的系统组装在一起,我将是一个快乐的程序员。 很棒的文章! 总的来说,我总是发现规模引人入胜。 Postgres 9.2 增加了对多达 64 个内核的支持(真正的支持),这确实使我很高兴。 业界似乎在“只是向它扔更多便宜的服务器...它们很便宜”和“让我们看看我们可以将其堆叠多高,因为很难将其拆分”之间来回切换。 我更喜欢后者,但是将它们结合在一起,再加上您所说的优化(不只是将大规模网络等任务委派给内核),往往会使我们朝着 roboblypse 前进:) 好贴。 对于内存可伸缩性,您还可以考虑通过使用 libnuma / numactl 之类的控件来控制进程亲和力,从而提高内存的局部性。 关于本次会议的非常好的总结 关于 DPDK,您可以从 http://dpdk.org 获得源代码。 它提供 git,邮件列表和良好的支持。 看来它是由 6WIND 驱动的。 尽管[通用可扩展性法律](http://is.gd/3N2Iia)(USL)在视频演示中显示的时间约为 30:00 分钟,但他声明可扩展性和性能无关。 请注意,由于多核一致性延迟的出现而导致的最大性能。 在 Velocity 2010 上提出了对[内存缓存](http://www.perfdynamics.com/Manifesto/USLscalability.html#tth_sEc4.3)的类似效果进行量化的方法。 这很有趣。 标题可能会更好,因为“ Linux 内核是问题”,因为其他内核则有所不同。 举个例子,我上次检查时,Linux 用了 29 个堆栈帧从 syscalls 转到 start_xmit()。 illumos / Solaris 内核的相似路径(对 mac_tx()的系统调用)采用 16。 FreeBSD 用了 10 个(对 ether_output()的系统调用)。 这些可以有所不同。 检查您的内核版本和工作量。 我已经将它们作为堆栈差异的示例。 这也应该使 Linux 堆栈更昂贵-但我需要分析(基于周期)以进行量化。 内存访问确实是大敌,您谈论的是保存缓存未命中,但是在 Linux(和其他内核)中,已经为 CPU 亲和力和内存局部性做了很多工作。 是行不通还是行不通? 是否有可以修复的错误? 分析这个问题并找出问题的根本原因将是非常好的。 在 Linux 上,运行 perf 并查看内核堆栈以查找缓存未命中。 更好的办法是量化 TCP / IP 中的内核堆栈,以获取内存访问停顿周期-并查看它们是否累加并解释了问题。 现在,我正在研究内核网络性能问题(我正在做内核工程)。 我认为我发现了一个内核错误,通过对问题进行根本原因分析,可以发现该内核错误可以将我正在运行的基准测试的网络堆栈延迟提高(减少)约 2 倍。 这样的胜利不会改变绕开堆栈的整体潜在胜利。 但是最好是先了解内核的限制是什么,然后再根源进行此操作。 绕过内核还意味着您可能需要重新发明一些工具集以进行性能分析(我使用了许多自定义工具,这些工具在系统调用和设备之间工作,用于分析 TCP 延迟和丢包,超出了网络嗅探的范围)。 让我想起了范雅各布森在 LCA2006 上的演讲。 谈论将工作推向端点。 而内核确实不是终结点(尤其是使用 SMP),而应用程序就是。 Unix 最初并未用于控制电话网络。 通常是一个用于编辑文档的分时系统(带标记的 ASCII 文本)。 这是从 CACM 纸的 BSTJ 纸版本中提取的。 http://cm.bell-labs.com/cm/cs/who/dmr/cacm.html。 自 1971 年 2 月 PDP-11 Unix 投入使用以来,已有 600 多个安装投入使用。 他们中的大多数人从事诸如计算机科学教育,文档和其他文本材料的准备和格式化,从 Bell 系统内的各种交换机收集和处理故障数据以及记录和检查电话服务订单等应用程序。 我们自己的安装程序主要用于操作系统,语言,计算机网络和计算机科学中的其他主题的研究,还用于文档准备。 让我们来看看 EZchip NPS,它实现了上面的大多数想法。 这并不奇怪:通用软件(例如内核)适用于“标准”应用程序。 为了达到最高性能,定制的,经过微调的软件总是可以击败它。 [Netmap](http://info.iet.unipi.it/~luigi/netmap/) 是否也不能很好地解决数据包 I / O 效率问题? 恩,我讨厌将其分解给你们,但是这个问题及其解决方案[早已为 exokernel 社区所熟知。](http://pdos.csail.mit.edu/exo.html) 虽然我承认 Linux 和 BSD 的商标意义是“不是 Unix”,但它们仍然基于不低于 60 年历史的 OS 体系结构(我们为之付出的大部分努力) 授予是来自 Multics 的某种形式的)。 现在是进行重大更新的时候了。 :) @Russell Sullivan 与本文无关的是外行。 “ Unix 最初并不是被设计为通用服务器操作系统,而是被设计为电话网络的控制系统。” 呃,不,这是完全错误的。 由于 Linux 内核是独立开发的,因此谈论 UNIX 是无关紧要的。 这并不是说技术论点是不正确的,但是这种荒谬的废话无助于信誉。 一个问题是用户空间和内核空间中存在的阻塞点(无论是共享数据结构还是互斥体,是否可并行化)。 外来内核和其他方法只是通过转移负担(IP 堆栈打包功能)来选择做同一件事的不同方法。 最终,硬件(真实或虚拟)在解决方案上呈现出最明显的有限瓶颈。 在包括硅在内的其他方法的最高端,http://tabula.com 以网络为中心的应用程序编译为带有功能样式编码的特定于应用程序的 OS 框架。 这不仅对利基问题是有前途的,而且似乎是解决时间/空间数据流问题的许多传统瓶颈的最深层方法。 对于 99%的解决方案,从用尽垂直规模的 LMAX 嵌入式系统开始使用 http://martinfowler.com/articles/lmax.html 开始,在精疲力尽商用设备之后,可能更明智。 回到商业规模,对于 Xen,有一些无操作系统的运行时: Erlang-LING VM Haskell-Halvm “ Unix 中的锁是在内核中实现的”主张对于当今的系统而言并非绝对正确。 如 http://en.wikipedia.org/wiki/Futex 中所述,我们具有轻巧的用户土地锁。 尽管我同意应用程序在执行网络数据包处理方面可能带来的速度提升,但是内存管理(包括分页)和 CPU 调度几乎不在应用程序的范围内。 这类事情应该留给对底层硬件有更好了解的内核开发人员。 有趣的是,“控制和数据分离”的架构模式多久出现一次。 前几天,我在一个充满高管人员的房间里发表了讲话,指出在我们正在开发的产品中这种模式是如何发生的(事实证明是不正确的)。 您可以在我在 NCAR 上工作过的各种大型海量存储系统中看到它(控制 IP 链接,但是使用专用硬件通过高速 I / O 通道进行数据处理),而在我当时工作过的各种大型电信系统中 在贝尔实验室(再次通过 IP 链路“发送信号”,但通过专用交换结构使用完全不同的传输机制在所有“承载”流量),在 VOIP 系统中(使用 SIP 进行控制并由软件处理,但 RTP 尽可能地桥接) 即使在嵌入式系统中(直接从 A / D 芯片通过 TDM 总线承载,但通过 SPI 串行总线通过控制消息进行控制),也可以直接在端点之间进行操作,而无需软件堆栈进行处理。 这种模式至少自 1960 年代就已经存在,甚至在更早的其他非数字控制环境中也是如此。 这实际上是专业劳动理念的一个部门,可以追溯到数千年前。 仅供参考:我们使用一台运行标准 Linux 的 1U 服务器(未更改源代码)实现了 1200 万个并发连接,同时以 1Gbps 以上的速度发布数据。 查看更多详细信息: http://mrotaru.wordpress.com/2013/06/20/12-million-concurrent-connections-with-migratorydata-websocket-server/ 但是,我同意,就大量套接字而言,Linux 内核仍应提供实质性的改进。 很高兴看到新版本的 Linux 内核(从 3.7 版开始)在套接字相关的内存占用方面有了一些重要的改进。 然而。 更多优化是必要且可能的。 如我的帖子所述,1200 万个并发连接的内存占用量约为 36 GB。 Linux 内核肯定可以增强此功能。 通过阅读本文,我得出结论,这是从头开始进行未来 OS 设计的新时代。 我尝试使用 lwip PF_RING,但失败了,从北京 IDF 2013 获悉 windriver 开发了它自己的用户空间堆栈,在 2 年内花费了 20 个开发人员。 这很棒! 对于我打算稍后用于商业用途的学校项目,我做错了方法(每个连接一个线程)。 这很棒! 我已经使用 nio 实现了 Java Web 服务器,并且可以在具有 5 年历史的 8GB ram 台式机上实现 10K +的连接-但是 10M 太疯狂了。 在 Linux 上,开放套接字的数量似乎受到 ulimit 的限制-并且不确定如果没有内核调整,是否甚至可以实现 10M。.我想您的方法并不重要。 很棒的帖子。 英特尔正在招聘 DPDK 和网络开发人员。 如果您知道有人对此空间感兴趣,请传递 http://jobs.intel.com/job/Santa-Clara-Networking-Developer-Evangelist-Job-CA-95050/77213300/ “ 1400 个时钟周期” 这是什么样的愚蠢,模棱两可的数字表达方式? 您是否在故意混淆 peple? 在整篇文章中,您应该*一贯*地使用数字或单词,更不用说相同的数字了。