nginx系列架构基础(2)---nginx事件
nginx是一个事件驱动的框架,所谓的事件主要指的是网络事件。nginx的每个连接对应两个网络事件,一个读事件;一个写事件。
网络事件
主机A是我们家里的电脑,主机B是我们的nginx服务器
- 应用层中我们发送了一个GET请求。
- 传输层中我们的浏览器打开了一个端口记录下来,同时nginx打开的端口(如80、443)也记录下来
- 网络层会记录下我们主机所在的IP,和目的地址所在的IP
- 从链路层经过以太网到达我们家中的路由器
- 家中的路由器会记录下我们运营商所用的IP地址,在通过广域网,最终会到达主机B
- 主机B在经过链路层、网络层、传输层。通过传输层就可以知道主机A是访问的主机B的80端口,这个对口对应nginx服务,在应用层的HTTP状态机中处理这个请求。
请求建立TCP连接事件:实际上就是发送一个TCP的报文,经过上边的流程到达nginx,其实是一个读事件。对于nginx来说就是读取了一个报文,就是Accept建立连接的事件
TCP连接可读事件:我们想nginx发送了一个消息,也是一个读事件,就是Read读消息
TCP连接关闭事件:我们的浏览器向nginx发送关闭连接的请求的TCP报文,还是一个读事件,就是Accept建立连接的事件
事件收集、分发器
事件是生产者,是通过网络中自动生产到nginx中的,我们要对每个事件建立一个消费者。
如连接建立的消费者,就是对Accept的调用。读事件消费者就是对Read的调用。不同的消费者调用不同的方法。
nginx事件循环
- nginx刚刚启动的时候我们处在
WAIT FOR EVENTS ON CONNECTIONS
,也就说我们打开了80或443端口,这个时候我们在等待新的事件进来。(如连接事件),这时我们的进程往往处于sleep的状态
- 当操作系统接受到一个握手报文,并处理完握手流程以后。系统通知
WAIT FOR EVENTS ON CONNECTIONS
可以往下走了,同时唤醒我们的worker进程
- 到达
RECEIVE A QUEUE OF NEW EVENTS
,者时候我们会向操作系统要事件,操作系统KERNEL(内核)会将事件放到一个队列中。通过这个队列我们可以获取到一个一个我们要处理的事件。
- 接着往下到达
PROCESS THE EVENTS QUEUE IN CYCLE
,开始处理事件。就是我们发现队列不为空,我们就把事件取出来,开始处理这个事件。在我们处理事件过程中可能会生成新的事件。加入到新的事件队列中,等待处理。
- 当我们的事件处理完成后又返回到
WAIT FOR EVENTS ON CONNECTIONS
epoll的优势及原理
通过上边的性能分析图表我们可以发现,随着句柄数的增加(并发连接数的增加),其它网络模型所消耗时间是急剧上升的。而epoll基本上和句柄数增加是无关的。
每次我处理事件时,虽然我总共有100万的并发连接,但是可能只有几百个活跃连接,我只需要处理几百个活跃连接就可以了。
epoll维护了eventpool和epitem的数据结构。这里通过两个数据结构把事件分开了。到nginx处理事件的时候只需要遍历一个链表,这个链表中只有活跃的连接的事件,这样我们的效率就很高。
当我们处理事件的时候会产生新的事件,我们都放到红黑树中。
nginx请求切换
当蓝色的请求不满足需要的时候它的用户态就,直接切换的绿色的请求,这样我们就没有了中间进程切换的一个成本,除非是我们nginx worker的时间片已经到了(时间片的长度大约是5毫秒到800毫秒)
所以,我们在nginx的worker的配置上往往把它的优先级加到最高,比如我们会加到-19,这要操作系统分配的时间片是比较大的,这样的话我们的nginx才能更好的在用户态完成请求的切换,减少CPU的无用功。