千万级并发实现的秘密:内核不是解决方案,而是问题所在!
既然我们已经解决了 C10K并发连接问题,应该如何提高水平支持千万级并发连接?你可能会说不可能。不,现在系统已经在用你可能不熟悉甚至激进的方式支持千万级别的并发连接。
要知道它是如何做到的,我们首先要了解Errata Security的CEO Errata Security,以及他在Shmoocon 2013大会上的无稽之谈 C10M Defending The Internet At Scale。
Robert用一种我以前从未听说的方式来很巧妙地解释了这个问题。他首先介绍了一点有关Unix的历史,Unix的设计初衷并不是一般的服务器操作系统,而是电话网络的控制系统。由于是实际传送数据的电话网络,所以在控制层和数据层之间有明确的界限。问题是我们现在根本不应该使用Unix服务器作为数据层的一部分。正如设计只运行一个应用程序的服务器内核,肯定和设计多用户的服务器内核是不同的。
也就是他所说的关键要理解内核不是解决办法,内核是问题所在。
这意味着:
不要让内核执行所有繁重的任务。将数据包处理,内存管理,处理器调度等任务从内核转移到应用程序高效地完成。让Linux只处理控制层,数据层完全交给应用程序来处理。
最终就是要设计这样一个系统,该系统可以处理千万级别的并发连接,它在200个时钟周期内处理数据包,在14万个时钟周期内处理应用程序逻辑。由于一次主存储器访问就要花费300个时钟周期,所以这是最大限度的减少代码和缓存丢失的关键。
面向数据层的系统可以每秒处理1千万个数据包,面向控制层的系统,每秒只能处理1百万个数据包。
这似乎很极端,请记住一句老话:可扩展性是专业化的。为了做好一些事情,你不能把性能问题外包给操作系统来解决,你必须自己做。
现在,让我们学习Robert如何创建一个能够处理千万级别并发连接的系统。
C10K问题最近十年
十年前,工程师处理C10K可扩展性问题时,尽量避免服务器处理超过1万个的并发连接。通过改进操作系统内核以及用事件驱动服务器(如Nginx和Node)代替线程服务器(Apache),这个问题已经被解决。人们用十年的时间从Apache转移到可扩展服务器,在近几年,可扩展服务器的采用率增长得更快了。
Apache的问题
Apache的问题在于服务器的性能会随着连接数的增多而变差
关键点:性能和可扩展性并不是一回事。当人们谈论规模时,他们往往是在谈论性能,但是规模和性能是不同的,比如Apache。
持续几秒的短期连接,比如快速事务,如果每秒处理1000个事务,只有约1000个并发连接到服务器。
事务延长到10秒,要维持每秒1000个事务,必须打开1万个并发连接。这种情况下:尽管你不顾DoS攻击,Apache也会性能陡降;同时大量的下载操作也会使Apache崩溃。
如果每秒处理的连接从5千增加到1万,你会怎么做?比方说,你升级硬件并且提高处理器速度到原来的2倍。发生了什么?你得到两倍的性能,但你没有得到两倍的处理规模。每秒处理的连接可能只达到了6000。你继续提高速度,情况也没有改善。甚至16倍的性能时,仍然不能处理1万个并发连接。所以说性能和可扩展性是不一样的。
问题在于Apache会创建一个CGI进程,然后关闭,这个步骤并没有扩展。
为什么呢?内核使用的O(N^2)算法使服务器无法处理1万个并发连接。
内核中的两个基本问题:
连接数=线程数/进程数。当一个数据包进来,内核会遍历其所有进程以决定由哪个进程来处理这个数据包。
连接数=选择数/轮询次数(单线程)。同样的可扩展性问题,每个包都要走一遭列表上所有的socket。
解决方法:改进内核使其在常数时间内查找。
使线程切换时间与线程数量无关。
使用一个新的可扩展epoll()/IOCompletionPort常数时间去做socket查询。
因为线程调度并没有得到扩展,所以服务器大规模对socket使用epoll方法,这样就导致需要使用异步编程模式,而这些编程模式正是Nginx和Node类型服务器具有的;所以当从Apache迁移到Nginx和Node类型服务器时,即使在一个配置较低的服务器上增加连接数,性能也不会突降;所以在10K连接时,一台笔记本电脑的速度甚至超过了16核的服务器。
C10M问题未来十年
不远的将来,服务器将要处理数百万的并发连接。IPv6协议下,每个服务器的潜在连接数都是数以百万级的,所以处理规模需要升级。
如IDS / IPS这类应用程序需要支持这种规模,因为它们连接到一个服务器骨干网。其他例子:DNS根服务器,TOR节点,互联网Nmap,视频流,银行,Carrier NAT,VoIP PBX,负载均衡器,网页缓存,防火墙,电子邮件接收,垃圾邮件过滤。
通常人们将互联网规模问题归根于应用程序而不是服务器,因为他们卖的是硬件+软件。你买设备,并将其应用到你的数据中心。这些设备可能包含一块Intel主板或网络处理器以及用来加密和检测数据包的专用芯片等。
截至2013年2月,40Gpbs,32芯,256G RAM 的X86处理器在Newegg网站上的报价是5000美元。该服务器可以处理1万个以上的并发连接,如果它们不能,那是因为你选择了错误的软件,而不是底层硬件的问题。这个硬件可以很容易地扩展到1千万个并发连接。
10M的并发连接挑战意味着什么:
我们所学的是Unix而不是网络编程
很多程序员通过W. Richard Stevens所著的《Unix网络编程》学习网络编程技术。问题是,这本书是关于Unix的,而不只是网络编程。它告诉你,让Unix做所有繁重的工作,你只需要在Unix的上层写一个小服务器。但内核规模不够,解决的办法是尽可能将业务移动到内核之外,并且自己处理所有繁重的业务。
这方面有影响的一个例子是Apache每个连接线程的模型。这意味着线程调度程序根据将要到来的数据确定接下来调用哪一个read()函数,也就是把线程调度系统当作数据包调度系统来用。(我真的很喜欢这一点,从来没有想过这样的说法)。
Nginx宣称,它不把线程调度当作数据包调度程序,而是自己进行数据包调度。使用select找到socket,我们知道数据来了,就可以立即读取并处理数据,数据也不会堵塞。
经验:让Unix处理网络堆栈,但之后的业务由你来处理。
怎样编写规模较大的软件?
如何改变你的软件,使其规模化?许多只提升硬件性能去支撑项目扩展的经验都是错误的,我们需要知道性能的实际情况。
要达到到更高的水平,需要解决的问题如下:
实现数据包可扩展编写自己的个性化驱动来绕过堆栈
数据包的问题是它们需经Unix内核的处理。网络堆栈复杂缓慢,数据包最好直接到达应用程序,而非经过操作系统处理之后。
做到这一点的方法是编写自己的驱动程序。所有驱动程序将数据包直接发送到应用程序,而不是通过堆栈。你可以找到这种驱动程序:PF_RING,NETMAP,Intel DPDK(数据层开发套件)。Intel不是开源的,但有很多相关的技术支持。
速度有多快?Intel的基准是在一个相当轻量级的服务器上,每秒处理8000万个数据包(每个数据包200个时钟周期)。这也是通过用户模式。将数据包向上传递,使用用户模式,处理完毕后再返回。Linux每秒处理的数据包个数不超过百万个,将UDP数据包提高到用户模式,再次出去。客户驱动程序和Linux的性能比是80:1。
对于每秒1000万个数据包的目标,如果200个时钟周期被用来获取数据包,将留下1400个时钟周期实现类似DNS / IDS的功能。
通过PF_RING得到的是原始数据包,所以你必须做你的TCP堆栈。人们所做的是用户模式栈。Intel有现成的可扩展TCP堆栈
多核的可扩展性
多核可扩展性不同于多线程可扩展性。我们都熟知这个理念:处理器的速度并没有变快,我们只是靠增加数量来达到目的。
大多数的代码都未实现4核以上的并行。当我们添加更多内核时,下降的不仅仅是性能等级,处理速度可能也会变得越来越慢,这是软件的问题。我们希望软件的提高速度同内核的增加接近线性正相关。
多线程编程不同于多核编程
多线程
每个CPU内核中不止一个线程
用锁来协调线程(通过系统调用)
每个线程有不同的任务
多核
每个CPU内核中只有一个线程
当两个线程/内核访问同一个数据时,不能停下来互相等待
同一个任务的不同线程
要解决的问题是怎样将一个应用程序分布到多个内核中去
Unix中的锁在内核实现。4内核使用锁的情况是大多数软件开始等待其他线程解锁。因此,增加内核所获得的收益远远低于等待中的性能损耗。
我们需要这样一个架构,它更像高速公路而不是红绿灯控制的十字路口,无需等待,每个人都以自己的节奏行进,尽可能节省开销。
解决方案:
在每个核心中保存数据结构,然后聚合的对数据进行读取。
原子性。CPU支持可以通过C语言调用的指令,保证原子性,避免冲突发生。开销很大,所以不要处处使用。
无锁的数据结构。线程无需等待即可访问,在不同的架构下都是复杂的工作,请不要自己做。
线程模型,即流水线与工作线程模型。这不只是同步的问题,而是你的线程如何架构。
处理器关联。告诉操作系统优先使用前两个内核,然后设置线程运行在哪一个内核上,你也可以通过中断到达这个目的。所以,CPU由你来控制而不是Linux。
内存的可扩展性
如果你有20G的RAM,假设每次连接占用2K的内存,如果你还有20M的三级缓存,缓存中会没有数据。数据转移到主存中处理花费300个时钟周期,此时CPU没有做任何事情。
每个数据包要有1400个时钟周期(DNS / IDS的功能)和200个时钟周期(获取数据包)的开销,每个数据包我们只有4个高速缓存缺失,这是一个问题。
联合定位数据
不要通过指针在满内存乱放数据。每次你跟踪一个指针,都会是一个高速缓存缺失:[hash pointer] -> [Task Control Block] -> [Socket] -> [App],这是四个高速缓存缺失。
保持所有的数据在一个内存块:[TCB |socket| APP]。给所有块预分配内存,将高速缓存缺失从4减少到1。
分页
32GB的数据需占用64MB的分页表,不适合都存储在高速缓存。所以存在两个高速缓存缺失分页表和它所指向的数据。这是开发可扩展的软件不能忽略的细节。
解决方案:压缩数据,使用有很多内存访问的高速缓存架构,而不是二叉搜索树
NUMA架构加倍了主存访问时间。内存可能不在本地socket,而是另一个socket上。
内存池
启动时立即预先分配所有的内存
在对象,线程和socket的基础上进行分配。
超线程
每个网络处理器最多可以运行4个线程,英特尔只能运行2个。
在适当的情况下,我们还需要掩盖延时,比如内存访问中一个线程在等待另一个全速的线程。
大内存页
减小页表规模。从一开始就预留内存,让你的应用程序管理内存。
总结
网卡
问题:通过内核工作效率不高
解决方案:使用自己的驱动程序并管理它们,使适配器远离操作系统。
CPU
问题:使用传统的内核方法来协调你的应用程序是行不通的。
解决方案:Linux管理前两个CPU,你的应用程序管理其余的CPU。中断只发生在你允许的CPU上。
内存
问题:内存需要特别关注,以求高效。
解决方案:在系统启动时就分配大部分内存给你管理的大内存页
控制层交给Linux,应用程序管理数据。应用程序与内核之间没有交互,没有线程调度,没有系统调用,没有中断,什么都没有。
然而,你有的是在Linux上运行的代码,你可以正常调试,这不是某种怪异的硬件系统,需要特定的工程师。你需要定制的硬件在数据层提升性能,但是必须是在你熟悉的编程和开发环境上进行。
数据分析咨询请扫描二维码
需求持续增长 - 未来数据分析师需求将持续上升,企业对数据驱动决策的依赖加深。 - 预测到2025年,中国将需要高达220万的数据人 ...
2024-11-22《Python数据分析极简入门》 第2节 4 Pandas条件查询 在pandas中,可以使用条件筛选来选择满足特定条件的数据 importpanda ...
2024-11-22数据分析师的工作内容涉及多个方面,主要包括数据的收集、整理、分析和可视化,以支持商业决策和问题解决。以下是数据分析师的一 ...
2024-11-21数据分析师必须掌握的技能可以从多个方面进行归纳和总结。以下是数据分析师需要具备的主要技能: 统计学基础:数据分析师需要 ...
2024-11-21数据分析入门的难易程度因人而异,总体来看,入门并不算特别困难,但需要一定的学习和实践积累。 入门难度:数据分析入门相对 ...
2024-11-21数据分析是一项通过收集、整理和解释数据来发现有用信息的过程,它在现代社会中具有广泛的应用和重要性。数据分析能够帮助人们更 ...
2024-11-21数据分析行业正在迅速发展,随着技术的不断进步和数据量的爆炸式增长,企业对数据分析人才的需求也与日俱增。本文将探讨数据分析 ...
2024-11-21数据分析的常用方法包括多种技术,每种方法都有其特定的应用场景和优势。以下是几种常见的数据分析方法: 对比分析法:通过比 ...
2024-11-21企业数字化转型是指企业利用数字技术对其业务进行改造和升级,以实现提高效率、降低成本、创新业务模式等目标的过程。这一过程不 ...
2024-11-21数据分析作为一个备受追捧的职业领域,吸引着越来越多的女性加入其中。对于女生而言,在选择成为一名数据分析师时,行业选择至关 ...
2024-11-21大数据技术专业主要学习计算机科学、数学、统计学和信息技术等领域的基础理论和技能,旨在培养具备大数据处理、分析和应用能力的 ...
2024-11-21《Python数据分析极简入门》 第2节 3 Pandas数据查看 这里我们创建一个DataFrame命名为df: importnumpyasnpi ...
2024-11-21越老越吃香的行业主要集中在需要长时间经验积累和专业知识的领域。这些行业通常知识更新换代较慢,因此随着年龄的增长,从业者能 ...
2024-11-20数据导入 使用pandas库的read_csv()函数读取CSV文件或使用read_excel()函数读取Excel文件。 支持处理不同格式数据,可指定分隔 ...
2024-11-20大数据与会计专业是一门结合了大数据分析技术和会计财务理论知识的新型复合型学科,旨在培养能够适应现代会计业务新特征的高层次 ...
2024-11-20要成为一名数据分析师,需要掌握一系列硬技能和软技能。以下是成为数据分析师所需的关键技能: 统计学基础 理解基本的统计概念 ...
2024-11-20是的,Python可以用于数据分析。Python在数据分析领域非常流行,因为它拥有丰富的库和工具,能够高效地处理从数据清洗到可视化的 ...
2024-11-20在这个数据驱动的时代,数据分析师的角色变得愈发不可或缺。他们承担着帮助企业从数据中提取有价值信息的责任,而这些信息可以大 ...
2024-11-20数据分析作为现代信息时代的支柱之一,已经成为各行业不可或缺的工具。无论是在商业、科研还是日常决策中,数据分析都扮演着至关 ...
2024-11-20数字化转型已成为当今商业世界的热点话题。它不仅代表着技术的提升,还涉及企业业务流程、组织结构和文化的深层次变革。理解数字 ...
2024-11-20