Nginx的事件驱动模型

1.网络收发与Nginx事件间的对应关系

主机A是我们家里的一台笔记本电脑,主机B是部署着Nginx的服务器,从主机A发送一个http的get请求
到主机B,在这样的过程中究竟经历了什么网络事件呢?

在数据流中,
1.主机A的应用层:发送一个http请求;
2.主机A的传输层:做一件事,浏览器打开一个端口,会将端口记下,并把Nginx打卡的端口比如说8080也记录到传输层;
3.主机A的网络层:记录我们主机A所在的IP和目标Nginx主机B的公网IP;
4.主机A的链路层:经过以太网到达我们家的路由器;
5.以太网->链路层->网络层->广域网->以太网:我们家的路由器会记录我们所在运营商的一些下一段的IP,经过广域网以后最终跳转到主机B所在的机器中;
6.主机B的链路层;
7.主机B的网络层;
8.主机B的传输层(此时操作系统知道是给打开了8080端口的进程,即主机B上的Nginx服务);
9.主机B的http状态处理机中就会处理这个请求.

TCP流与报文:
数据链路层:添加源mac和目的mac地址;
网络层:    添加浏览器的公网IP和Nginx的公网IP;
TCP层:     指定了Nginx打开的端口和浏览器打开的端口;
应用层:     HTTP协议

经过这么多层的组装,组成了一个完整的可以在网络世界里遨游并寻找到目标进程的报文,
一个HTTP协议可以切割成很多小的报文:
网络层会切掉MTU(以太网的MTU是1500字节);
TCP层会考虑中间每个环节中的最大的一个MTU值,这时往往我们每个报文只有几百字节,这个报文大小称作
MSS,每收到一个MSS(小于MTU值)时,就是一个网络事件.    

 

 

2.TCP协议与非阻塞接口

请求建立TCP连接事件(发送一个TCP报文,是一个读事件,对于Nginx来说读到了一个报文,Accept建立连接)
TCP连接可读事件(发送了一个消息,对Nginx来说也是读事件,Read读事件)
TCP连接关闭事件(关闭连接的一个事件,对Nginx来说也是读事件)
TCP连接可写事件(对Nginx来说也是写事件)
异步读AIO磁盘成功事件(对Nginx来说也是读事件)



请求建立TCP连接事件---Nginx是连接建立事件消费者
TCP连接可读事件    ---Nginx是读事件消费者
TCP连接关闭事件    ---Nginx是连接关闭事件消费者
TCP连接可写事件    ---Nginx是写事件消费者
异步读磁盘成功事件  ---Nginx是异步读磁盘事件消费者
以上事件触发定时器到期事件.

所以对于TCP协议来说,Nginx会有以上6种小类事件.

 

3.Nginx事件循环

    当Nginx刚启动时,此时Nginx处于等待新的事件进来的状态(wait for evensts on connections),
比如说等待新的客户端连上我们的Nginx,向我们的Nginx发起连接请求,这个状态对应着epoll中的
epoll_wait的一个方法,此时Nginx处于sleep的一个进程状态,当操作系统收到了一个建立tcp连接的
握手报文并且处理完握手流程以后,操作系统就会通知epoll_wait方法告诉它可以往下运行了,同时唤醒
nginx的worker进程,往下走了之后就去找操作系统kernel中要事件,操作系统会把准备好的时间放在事件
队列中,从事件队列中可以获取到一个一个要处理的时间(如建立连接或者tcp的请求报文),将其从请求
队列中取出,取出之后,就会处理这样一个事件.
    
    右图是处理事件的一个循环,发现队列中不为空,就将事件取出开始处理事件,在处理事件的过程中可能生成新的事件,比如说发现新的连接,
可能需要添加一个超时事件,比如说60秒,如果60秒之内如果浏览器不给我发送请求的话,就会把连接关掉,又比如说,当我发现我收完了完整的
http请求后,已经可以生成http响应了,http响应是需要我可以向操作系统的写缓冲区中把响应写进去,要求操作系统尽快的把这段内容发到浏
览器上,此时就期待一个写事件;也就是说我们在处理事件的过程中可能会出现新的事件,生成新的队列,等待下一次来处理.如果所有的事件都
处理完成了,我们又会回到wait for evensts on connections这里.就有这样一个流程.

    了解Nginx事件循环有助于我们分析一些场景,比如说使用一些第三方模块的时候,这些第三方模块可能会做
大量的CPU运算,这样的计算任务会导致处理一个事件的任务非常长,会导致后序队列中的大量事件长时间得不到
处理,从而引发恶性循环(其他事件的超时事件到了),大量CPU都消耗在这些处理上,导致其他的连接不正常的
断开,所以往往Nginx不能容忍有些第三方模块长时间地消耗大量的CPU进行计算任务.我们可以看到包括gzip等
第三方模块都不会一次使用大量的CPU,而是分段使用.

 

 

4.epoll的优劣和原理

 

 

select,poll和epoll的一个质的关键飞跃就是:
epoll能快速地从内核中得到需要操作的事件.


问题:为什么epoll的效率会比poll和select相对高?
epoll维护了双向链表,双向链表中只有活跃的请求,不做无用功.

什么时候双向链表的数据会增减?
当我们读取一个数据的时候,这个数据就会从链表中删除;
当操作系统接收到网卡中发送来的一个报文的时候,这个链表就会增加一个新的元素.
rdllink(ready的链表)

epoll是一个网络事件收集器模型.

5.Nginx的请求切换

  如图中传统的服务器中,比如说有三个处理流程,第一次不满足的时候,操作系统就通过内核切换到第二个
处理流程中,第二个不满足的时候,就通过内核切换到第三个流程中,此时轮到第一个流程运转了,再通过
内核切换到第一个流程中,一次切换大概需要5微妙,操作系统的进程调度这对于成百上千的请求来说还可以
接受,但是一旦并发量大起来,就会变得稍微难以接受.

  Nginx中如何处理进程间的切换呢?当蓝色部分不满的时候,直接就在用户态切换到了绿色的请求,这样就没有
了操作系统中的进程切换的成本--类似协程概念(因为网络事件不满足),除非Nginx的worker所使用的的时间片到了,
这样才去进行内核的进程切换,一般来说时间片的长度是5毫秒-800毫秒,在Nginx的配置上往往会将workrt进程的
优先级加到最高(-19),此时操作系统给我们分配的时间片是比较多的,这样Nginx可以在用户态完成请求的切换,
使得CPU少做无用功.

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值