导入Nginx处理IO的方式是异步非阻塞的。Nginx之所以有高性能,除了异步和非阻塞之外,还有IO多路复用。什么是IO多路复用?从最简单的例子说起,一个请求连接过来之后,正常情况下你是怎么处理这个请求的?如图1所示,浏览器的每个请求都会分配或启动一个新的进程,并相应地处理该请求。在进程上下文之间切换并启动新进程会浪费资源。如何优化呢?(举手)把多入口变成多线程。然后就是如下图2所示的优化结果。这样做有什么问题?想一想,线程是进程调度的最小单位。一个进程有多个线程同时处理请求。如果进程因为异常情况意外终止,那么它拥有的所有线程都会终止,换句话说,服务会挂掉。哈哈,太刺激了。那么IO多路复用就派上用场了~~前面我们提到了异步非阻塞,所以我们这样设计,我们设计了一个进程池,事件响应守护进程,请求服务进程。那么,我们服务器的进程架构如下图所示:如上图所示,我们将服务器分为三个模块:进程池事件响应事件注册当浏览器请求到达服务器时,首先连接到(3)请求服务流程,并注册一个事件。当请求发送数据时,此时会产生一个read事件。此时,(2)事件响应进程会响应,事件会交给(1)进程池处理,同时会注册一个写事件。进程池处理完请求后,会响应write事件,将处理结果返回给浏览器。那么什么是IO多路复用呢?IO多路复用就是用一个进程去响应真正的请求事件。本质上复用的是过程。Select和Epoll当有读或写事件发生时,事件守护进程响应进程池进行处理,同时注册一个写事件,但是进程池怎么知道哪个socket有事件呢?所以每次事件发生时,事件响应过程都会遍历所有的socket连接句柄来判断是否有事件发生。这种响应事件的方式称为Select模型。如何优化呢?如果每次事件发生时,如果能够准确知道socket连接事件,效率会很高。这种方法就是epoll模型。比如餐厅有人要结账,服务员会告诉老板:“有人要结账”,老板不知道哪张桌子需要结账,需要一一询问.该方法为select,时间复杂度为O(n)。如果餐厅有人要结账,服务员会告诉老板:“5号桌需要结账”,这个方法是epoll,时间复杂度是O(1)。大视角理解高性能服务器的演进过程。总结一下:pool的概念会大大提高性能。这次我们说的是进程池。相同的。扩展:引入池的优化方法是很常见的。比如数据库连接池等等。有兴趣的可以去看看。下一篇文章会继续详细介绍,事件响应的两种方式:Reactor模式Proactor模式
