1. WEB请求处理机制
1.1. WEB 服务器常用的处理请求方式
1.1.1. 多进程方式
Apache 的 Prefork 模式就是多进程处理方式,当收到客户端的请求时,由服务器的主进程生成一个子进程来和该客户端进行交互。
该方式的优势是各个进程之间相互隔离,保证的服务器的稳定性。但是缺点很明显,对服务器的资源,尤其是内存的消耗很大,进程之间的上下文切换太重量级了,不适合大并发的场景。
1.1.2. 多线程的方式
Apache 的 worker模式和event模式就是多线程方式,当收到客户端的请求时,由服务器的工作进程生成一个线程来处理。
该方式的优势是大大增强了服务器处理并发请求的能力,但是socket本身是阻塞状态的,当有10万并发连接访问时,就需要10万的线程来维护这些请求,线程的上下文切换非常平台,会引发很严重的性能问题。
1.1.3. 异步方式
- 同步和异步
同步是指在发送方发出消息后,需要等待接收到接收方发回的响应,或者通过回调函数来接收到对方响应信息。
异步是指在发送方发出请求后,接收方不返回消息或者不等待返回消息。
- 阻塞和非阻塞
在网络通讯中,阻塞和非阻塞主要是指Socket的阻塞和非阻塞方式,而socket的实质是IO操作。
阻塞是指在IO操作返回结果之前,当前的线程处于被挂起状态,直到调用结果返回后才能处理其它新的请求。
非阻塞指在IO操作返回结果之前,当前的线程会继续处理其它的请求。
- 同步阻塞方式(常用,简单)
发送方向接收方发送请求后,一直处理等待响应状态。接收方处理请求时进行IO操作,如果该操作没有立刻返回结果,将继续等待,直到返回结果后,才响应发送方,期间不能处理其它请求。
- 异步非阻塞(常用)
发送方向接收方发送请求后,继续进行其它工作。接收方处理请求进行IO操作,如果没有立刻返回结果,将不再等待,而是处理其它请求。
1.2. Nginx服务器处理请求的方式
1.2.1. Nginx的异步非阻塞
Nginx 在服务启动后会产生一个主进程(master process)、多个工作进程(worker processes)、缓存加载进程(cache load processes)、缓存管理进程(cache manager processes),工作进程用于接收和处理客户端请求。
每个工作进程使用了异步非阻塞的方式,可以处理多个客户端的请求。当某个工作进程接收到客户端的请求后,使用事件驱动方式管理socket,将socket设置为非阻塞方式。
在涉及IO操作时,可以调用Linux文件系统提供的AIO接口,使用异步IO方式完成调用,针对任务繁重的IO操作可以将等待IO的操作卸载给线程池中其它线程处理,从而避免主线程(worker进程的主循环)阻塞。
1.2.2. Nginx处理请求的过程
2. 事件驱动模型
2.1. SELECT 库
各个版本的Linux和Windows平台都支持的基本事件驱动模型,并在接口定义上基本相同,使用步骤如下
- 创建所关注事件的描述符集合,对于一个描述符,可以关注其上面的读(read),写(write),异常(Exception)事件,所以要创建三类文件描述符集合。
- 调用底层提供的select()函数,等待事件发生。
- 轮询所有事件描述符集合中的每一个事件描述符,检查是否有相应的事件发生。
Nginx在安装时未指定其它高性能事件驱动模型库,会自动编译安装该库。
2.2. POLL 库
Poll库是Linux平台的事件驱动模型,在Linux 2.1.23中引入。
Poll库与Select类似,区别是select会创建三类事件描述符,而poll只创建一类描述符集合,所以缩减了轮询的时间。
Nginx在安装时未指定其它高性能事件驱动模型库,会自动编译安装该库。
2.3. EPOLL库
无论是SELECT还是POLL事件驱动模型,都是需要使用轮询的方法检查连接是否有新的事件,在连接数非常多的时候,轮询会非常消耗性能。
Epoll库是Linux高性能事件驱动模型库,其效率远超poll和select库。Linux 2.6及以上的版本都可以使用。
- 首先,当有新的socket连接时,nginx使用epoll库创建与socket相关联的文件描述符,并设置需要关注的事件,并将其添加到内核事件列表中。
- 然后,epoll库等待内核通知即可。省掉了select和poll库中轮询文件描述符的步骤。
Epoll库支持一个进程打开最大数目的事件描述符,上限是系统可以打开文件的最大数目;同时epoll库的IO效率不随文件描述符的增加而线性下降,因为它只会对内核上报的”活跃的描述符进行操作。
3. Nginx的进程
3.1 进程的分类
3.1.1. master process
Nginx启动时运行的主要进程,主要功能如下
- 读取Nginx配置文件
- 建立、绑定、关闭socket.
- 按照配置生成、管理进程.
- 接收外界指令,如重启、退出等
- 编译和处理Perl脚本
-
3.1.2. worker processes
接收并处理客户端请求
- 访问和调用缓存数据
- 接收主程序的指令
3.1.3. cache loader
在开启缓存服务器功能下,在Nginx主进程启动一段时间后(默认1分钟),由主进程生成cache loader,在缓存索引建立完成后将自动退出。3.1.4. Cache Manager
在开启缓存服务器功能下,在Nginx主进程的整个生命周期内,管理缓存索引,主要对索引是否过期进程判断。3.2. 进程之间的交互
3.2.1. 主进程与工作进程的交互
主进程生成工作进程的时候,会将工作进程添加到工作进程列表中,并建立一个主进程到工作进程的单向管道。当主进程需要与工作进程进行交互时,主进程通过管道向工作进程发出指令,工作进程读取管道中的数据。3.2.2. 工作进程与工作进程的交互
主进程在生成工作进程时,会将工作进程添加到工作进程列表中,并将该进程的ID等信息通过管道传递给其他进程。
当工作进程需要与其他工作进程通讯时,会从主进程给予的工作进程信息中找到对方进程的ID,然后建立与对方进程的管道,进行信息传递。