首页 文章 正文 Nginx-零拷贝 2024-03-19 951阅读 0评论 一、零拷贝(Zero Copy) 1.1、零拷贝基础 零拷贝指的是,从一个存储区域到另一个存储区域的copy任务没有CPU参与。零拷贝通常用于网络文件传输,以减少CPU消耗和内存带宽占用,减少用户空间(用户可以操作的内存缓存区域)与CPU内核空间(CPU可以操作的内存缓存区域及寄存器)的拷贝过程,减少用户上下文(用户状态环境)与CPU内核上下文(CPU内核状态环境)间的切换,提高系统效率。 DMA控制器Direct Memory Access,直接内存存取。 ALU算术逻辑运算器 1.2、传统拷贝方式 下面均以“将一个硬盘中的文件通过网络发送出去”的过程为例,来详细分析不同拷贝方式的实现细节。 首先通过应用程序的read()方法将文件从硬盘读取出来,然后再调用send()方法将文件发送出去。 发生4次空间切换,发生4次copy,其中有2次CPU参与。 1.3、零拷贝方式 Linux系统(CentOS6及其以上版本)对于零拷贝是通过sendfile系统调用实现的。 发生2次空间切换,发生3次copy,其中有0次CPU参与。 1.4、Gather Copy DMA零拷贝方式 由于该拷贝方式是由DMA完成,与系统无关,所以只要保证系统支持sendfile系统调用功能即可。 该方式中没有数据拷贝到socket buffer。取而代之的是只是将kernel buffer中的数据描述信息写到了socket buffer中。数据描述信息包含了两方面的信息:kernel buffer中数据的地址及偏移量。 发生2次空间切换,发生2次copy,其中有0次CPU参与。 1.5、mmap零拷贝 mmap零拷贝是对零拷贝的改进。当然,若当前主机的DMA支持Gather Copy,mmap同样可以实现Gather Copy DMA的零拷贝。 该方式与零拷贝的唯一区别是,应用程序与内核共享了Kernel buffer。由于是共享,所以应用程序也就可以操作该buffer了。当然,应用程序对于Kernel buffer的操作,就会引发用户空间与内核空间的相互切换。 发生4次空间切换,发生2次copy,其中有0次CPU参与。 二、多路复用器select|poll|epoll 2.1、基本知识 理解select、poll与epoll多路复用器的工作原理,就需要首先了解什么是多路复用器。而要了解什么是多路复用器,就需要先了解什么是“多进程/多线程连接处理模型”。 A、多进程/多线程连接处理模型 在该模型下,一个用户连接请求会由一个内核进程处理,而一个内核进程会创建一个应用程序进程,即app进程来处理该连接请求。应用程序进程在调用IO时,采用的是BIO通讯方式,即应用程序进程在未获取到IO响应之前是处于阻塞态的。 B、多路复用连接处理模型 在该模型下,只有一个app进程来处理内核进程事务,且app进程一次只能处理一个内核进程事务。故这种模型对于内核进程来说,存在对app进程的竞争。 2.2、多路复用器工作原理 A、select select多路复用器是采用轮询的方式,一直在轮询所有的相关内核进程,查看它们的进程状态。若已经就绪,则马上将该内核进程放入到就绪队列,该就绪队列底层由数组实现。 否则,继续查看下一个内核进程状态。在处理内核进程事务之前,app进程首先会从内核空间中将用户连接请求相关数据复制到用户空间。 B、poll poll多路复用器的工作原理与select几乎相同,不同的是,由于其就绪队列由链表实现,所以,其对于要处理的内核进程数量理论上是没有限制的,即其能够处理的最大并发连接数量是没有限制的(当然,要受限于当前系统中进程可以打开的最大文件描述符数ulimit,后面会讲到)。 C、epoll epoll多路复用是对select与poll的增强与改进。其不再采用轮询方式了,而是采用回调方式实现对内核进程状态的获取:一旦内核进程就绪,其就会回调epoll多路复用器,进入到多路复用器的就绪队列(由链表实现)。所以epoll多路复用模型也称为epoll事件驱动模型。 另外,应用程序所使用的数据,也不再从内核空间复制到用户空间了,而是使用mmap零拷贝机制,大大降低了系统开销。 当内核进程就绪信息通知了epoll多路复用器后,并不是马上对其进行处理,将其立即存放到就绪队列,而是根据不同的处理模型,有不同的处理方式。两种模型:LT模型与ET模型。 LT,Level Trigered,若没有将其存放到就绪队列,其会一直重试,直到加入到就绪队列,或取消了本次请求。 ET,Edge Trigered,若没有将其存放到就绪队列,则直接取消本次请求。所以其会存在请求丢失的情况,但其效率很高。 三、Nginx的并发处理机制 一般情况下并发处理机制有三种:多进程、多线程,与异步机制。Nginx对于并发的处理同时采用了三种机制。当然,其异步机制使用的是异步非阻塞方式。 我们知道Nginx的进程分为两类:master进程与worker进程。每个master进程可以生成多个worker进程,所以其是多进程的。每个worker进程可以同时处理多个用户请求,每个用户请求会由一个线程来处理,所以其是多线程的。 那么,如何解释其“异步非阻塞”并发处理机制呢? worker进程采用的就是epoll多路复用机制来对后端服务器进行处理的。当后端服务器返回结果后,后端服务器就会回调epoll多路复用器,由多路复用器对相应的worker进程进行通知。此时,worker进程就会挂起当前正在处理的事务,拿IO返回结果去响应客户端请求。响应完毕后,会再继续执行挂起的事务。这个过程就是“异步非阻塞”的。
发表评论
还没有评论,来说两句吧...