- 文章正文
- 我要评论(1)
网银互联:大流量数据如何处理?
来源: 未知 2016-10-19 杭州信息之窗当我们遇到数据过多时,会常常这么形容,”海量数据“、”大流量数据”,这些形容太抽象了,那么我们就具体一点,什么叫海量数据呢?
通俗地讲,像大海一样,或者说像天上的星星一样多的数据,用计算机术语来说就是T,P,Z级别的数据。这样形容相对来说有了一个比较感性的认识,对于我们计算机来说是如何处理海量数据的呢?
早些年,有一个问题困扰大家,就是C10k问题。什么是C10k问题,字面意思connect 10000,网络服务在处理数以万计的客户端连接时,往往出现效率低下甚至完全瘫痪,这被称为C10k问题。我们是如何处理的呢?简单来说放弃select等模式,采用epoll,kqueue,dev/poll来捕获I/O事件,很好的解决了C10k问题。可是随着互联网和移动互联网的发展,数据量太大了,计算机面对的不再是C10k问题,而是C10M问题。传统处理C10k问题的解决方案已经不能处理C10M问题。我们分析具体原因?
C10M,顾名思义connect 10000000,处理千万级别的连接数。
10,000,000个并发连接挑战意味着什么
1. 10,000,000个并发连接
2. 每秒1,000,000个连接——每个连接大约持续10秒
3. 10千兆比特/每秒——快速连接到互联网。
4. 10,000,000包/每秒——预期当前服务器处理50,000包/每秒,这将导致更高的级别。服务器能够用来处理每秒100,000个中断和每个包引发的中断。
5. 10微秒延迟——可扩张的服务器也许能够处理这样的增长,但是延迟将会很突出。
6. 10微秒上下跳动——限制最大延迟
7. 10个一致的CPU内核——软件应该扩张到更多内核。典型的软件只是简单的扩张到四个内核。服务器能够扩张到更多的内核,所以软件需要被重写以支持在拥有更多内核的机器上运行。
传统linux内核是如何处理数据包的
在传统的 Linux 模式下,系统接收数据包和将数据包发送出系统的过程占了包处理中很大一部分时间,这可能会出乎有些人的预料。换句话说,即使用户空间应用程序什么都不做,而只是将数据包从接收端口传送到发送端口,那么仍然会花费大量的处理时间。当网卡从网络接收到一个数据帧后,会使用直接内存访问( DMA)将数据帧传送到针对这一目的而预先分配的内核缓冲区内,更新适当的接收描述符环,然后发出中断通知数据帧的到达。操作系统对中断进行处理,更新环,然后将数据帧交给网络堆栈。网络堆栈对数据进行处理,如果数据帧的目的地是本地套接字,那么就将数据复制到该套接字,而拥有该套接字的用户空间应用程序就接收到了这些数据。进行传输时,用户应用程序通过系统调用将数据写入到一个套接字,使 Linux 内核将数据从用户缓冲区复制到内核缓冲区中。然后网络堆栈对数据进行处理,并根据需要对其进行封装,然后再调用网卡驱动程序。网卡驱动程序会更新适当的传输描述符环,并通知网卡有一个等待处理的传输任务。网卡将数据帧从内核缓冲区转移到自己内置的先进先出( FIFO)缓冲区,然后将数据帧传输到网络。接着网卡会发出一个中断,通知数据帧已经成功传输,从而使内核释放与该数据帧相关的缓冲区。
所以使用传统linux内核出去最高才有1Mpps的包数处理能力,远远达不到10M的数据量。
如果我们避免内核这个中间环节,就会省去很多消耗时间,提升我们的处理能力。绕过内核是个解决途径。
Intel DPDK就是这方面最好的实现。在六核 2.4 GHz英特尔至强处理器 E5645上以这种模式运行 Intel DPDK 时,对于使用六个核中的四个核、每个核一个线程、四个 10G 以太网端口的情况,使用流分类的 64 字 节 数 据 包 的 IP 第 三 层 转 发 性 能 达 到 了35.2Mpps。当在六核2.0 GHz 英特尔至强处理器 L5638 上使用最长前缀匹配( LPM)时,对于使用六个核心中的四个核心、每个核一个线程、四个 10G 以太网端口的情况, 64 字节数据包的 IP 第三层转发性能达到了 41.1Mpps。这比原始 Linux 的性能差不多提高了十倍(原始 Linux 在双处理器六核2.4GHz 模式下的性能为 12.2Mpps)。
DPDK是如何做到的呢,简单来说:使用轮询替代中断模式;将每一个进程单独绑定到一个核心上,并让CPU从这些核上隔离开来;批量操作来减少内存和PCI设备的访问;使用预取和对齐方式来提供CPU执行效率;减少多核之间的数据共享并使用无锁队列;使用大页面。
详细来说
PMD
当前Linux操作系统都是通过中断方式通知CPU来收发数据包,我们假定网卡每收到10个据包触发一次软中断,一个CPU核心每秒最多处理2w次中断,那么当一个核每秒收到20w个包时就占用了100%,此刻它没做其它任何操作。DPDK针对Intel网卡实现了基于轮询方式的PMD(Poll Mode Drivers)驱动,该驱动由API、用户空间运行的驱动程序构成,该驱动使用无中断方式直接操作网卡的接收和发送队列(除了链路状通知仍必须采用中断方式以外)。目前PMD驱动支持Intel的大部分1G、10G和40G的网卡。PMD驱动从网卡上接收到数据包后,会直接通过DMA方式传输到预分配的内存中,同时更新无锁环形队列中的数据包指针,不断轮询的应用程序很快就能感知收到数据包,并在预分配的内存地址上直接处理数据包,这个过程非常简洁。如果要是让Linux来处理收包过程,首先网卡通过中断方式通知协议栈对数据包进行处理,协议栈先会对数据包进行合法性进行必要的校验,然后判断
数据包目标是否本机的socket,满足条件则会将数据包拷贝一份向上递交给用户socket来处理,不仅处理路径冗长,还需要从内核到应用层的一次拷贝过程。大页表为实现物理地址到虚拟地址的转换,Linux一般通过查找TLB来进行快速映射,如果在查找TLB没有命中,就会触发一次缺页中断,将访问内存来重新刷新TLB页表。Linux下默认页大小为4K,当用户程序占用4M的内存时,就需要1K的页表项,如果使用2M的页面,那么只需要2条页表项,这样有两个好处:第一是使用hugepage的内存所需的页表项比较少,对于需要大量内存的进程来说节省了很多开销,像oracle之类的大型数据库优化都使用了大页面配置;第二是TLB冲突概率降低,TLB是cpu中单独的一块高速cache,一般只能容纳100条页表项,采用hugepage可以大大降低TLB miss的开销。DPDK目前支持了2M和1G两种方式的hugepage。通过修改默认/etc/grub.conf中hugepage配置为“default_hugepagesz=1Ghugepagesz=1G hugepages=32 isolcpus=022”,然后通过mount –
thugetlbfs nodev /mnt/huge就将hugepage文件系统hugetlbfs挂在/mnt/huge目录下,然后用户进程就可以使用mmap映射hugepage目标文件来使用大页面了。测试表明应用使用大页表比使用4K的页表性能提高10%~15%。
CPU亲缘性
多线程编程早已不是什么新鲜的事物了,多线程的初衷是提高整体应用程序的性能,但是如果不加注意,就会将多线程的创建和销毁开销,锁竞争,访存冲突,cache失效,上下文切换等诸多消耗性能的因素引入进来。这也是Ngnix使用单线程模型能获得比Apache多线程下性能更高的秘籍。为了进一步提高性能,就必须仔细斟酌考虑线程在CPU不同核上的分布情况,这也就是常说的多核编程。多核编程和多线程有很大的不同:多线程是指每个CPU上可以运行多个线程,涉及到线程调度、锁机制以及上下文的切换;而多核则是每个CPU核一个线程,核心之间访问数据无需上锁。为了最大限度减少线程调度的资源消耗,需要将Linux绑定在特定的核上,释放其余核心来专供应用程序使用。同时还需要考虑CPU特性和系统是否支持NUMA架构,如果支持的话,不同插槽上CPU的进程要避免访问远端内存,尽量访问本端内存。
减少内存访问
运算指令的执行速度是非常快,大多数在一个CPU cycle内就能完成,甚至通过流水线一个cycle能完成多条指令。但在实际执行过程中,处理器需要花费大量的时间去存储器来取指令和数据,在获取到数据之前,处理器基本处于空闲状态。那么为了提高性能,缩短服务器响应时间,我们可以怎样来减少访存操作呢?
(1)少用数组和指针,多用局部变量。因为简单的局部变量会放到寄存器中,而数组和指针都必
须通过内存访问才能获取数据;
(2)少用全局变量。全局变量被多个模块或函数使用,不会放到寄存器中。
(3)一次多访问一些数据。就好比我们出去买东西一样,一次多带一些东西更省时间。我们可以
使用多操作数的指令,来提高计算效率,DPDK最新版本配合向量指令集(AVX)可以使CPU处
理数据包性能提升10%以上。
(4)自己管理内存分配。频繁调用malloc和free函数是导致性能降低的重要原因,不仅仅是函数
调用本身非常耗时,而且会导致大量内存碎片。由于空间比较分散,也进一步增大了cache
misses的概率。
(5)进程间传递指针而非整个数据块。在高速处理数据包过程中特别需要注意,前端线程和后端
[责任编辑:]
-
上一篇:[独家] 草根创业者的英雄之路——刘维亚
下一篇:没有了
已有1条评论