Nginx 是一个事件驱动的框架,所谓事件主要指的是网络事件,Nginx 每一个网络链接会对应两个网络事件,一个读事件一个写事件。在深刻了解 Nginx 各类原理及在极端场景下的一些错误场景处理时,须要首先理解什么是网络事件。windows
接下来看上面这张图,好比主机 A 就是一台家里的笔记本电脑,那么主机 B 就是一台服务器,上面跑着 Nginx 服务。从主机 A 发送一个 HTTP 的 GET 请求到主机 B,这样的一个过程当中主要经历了哪些事件?经过上图数据流部分能够看出:浏览器
应用层里发送了一个 GET 请求 -> 到了传输层,这一步主要在作一件事,就是浏览器打开了一个端口,在 windows 的任务管理器中能够看到这一点,他会把这个端口记下来以及把 Nginx 打开的端口好比 80 或者 443 也记到传输层 -> 而后在网络层会记下咱们主机所在的 IP 和目标主机,也就是 Nginx 所在服务器公网 IP -> 到链路层之后 -> 通过以太网 -> 到达家里的路由器(网络层),家中的路由器会记录下所在运营商的一些下一段的 IP -> 经过广域网 -> 跳转到主机 B 所在的机器中 -> 报文会通过链路层 -> 网络层 -> 到传输层,在传输层操做系统就知道是给那个打开了 80 或者 443 的进程,这个进程天然就是 Nginx -> 那么 Nginx 在他的 HTTP 状态处理机里面(应用层)就会处理这个请求。服务器
在上述过程当中网络报文扮演了一个怎样的角色呢?网络
数据链路层会在数据的前面 Header 部分和 Footer 部分添加上源 MAC 地址和源目的地址 -> 到了网络层则是 Nginx 的公网地址(目的 IP 地址)和浏览器的公网地址(源 IP 地址)-> 到了 TCP 层(传输层),指定了 Nginx 打开的端口(目的端口)和浏览器打开的端口(源端口)-> 而后应用层就是 HTTP 协议了。框架
这就是一个报文,也就是说咱们发送的 HTTP 协议会被切割成不少小的报文,在网络层会切割叫 MTU,以太网的每一个 MTU 是 1500 字节;在 TCP 层(传输层)呢会考虑中间每一个环节中最大的一个 MTU 值,这个时候每每每一个报文只有几百字节,这个报文大小咱们称为叫 MSS ,因此每收到一个 MSS 小于这么大小的一个报文时其实就是一个网络事件。异步
这个时候,咱们来看下 TCP 协议中许多事件是怎样和咱们平常调用的一些接口(好比 Accept、Read、Write、Close)是怎样关联在一块儿的?工具
请求创建 TCP 链接事件其实是发送了一个 TCP 报文,经过上面第二部分讲解的那样的一个流程到达了 Nginx,对应的是读事件。由于对于 Nginx 来讲,我读取到了一个报文,因此就是 Accept 创建连接事件。操作系统
若是是 TCP 链接可读事件,就是发送了一个消息,对于 Nginx 也是一个读事件,就是 Read 读消息。blog
若是是对端(也就是浏览器)主动地关掉了,至关于 windows 操做系统会去发送一个要求关闭连接的一个事件,对于 Nginx 来讲仍是一个读事件,由于他只是去读取一个报文。接口
那什么是写事件呢?当咱们的浏览器须要向浏览器发送响应的时候,须要把消息写到操做系统中,要求操做系统发送到网络中,这就是一个写事件。
像这样的一些网络读写事件,一般在 Nginx 中或者任何一个异步事件的处理框架中,他会有个东西叫事件收集、分发器。会定义每类事件处理的消费者,也就是说事件是一个生产者,是经过网络中自动的生产到咱们的 Nginx 中的,咱们要对每种事件创建一个消费者。好比链接创建事件消费者,就是对 Accept 调用,HTTP 模块就会去创建一个新的链接。还有不少读消息或者写消息,在 HTTP 状态机中不一样的时间段会调用不一样的方法也就是每一个消费者处理。
以上就是一个事件分发、消费器,包括 AIO 像异步读写磁盘事件,还有定时器事件,好比是否超时(worker_shutdown_timeout)。
上面介绍了网络报文的发送以及对应的 Nginx 中的网络事件,好比 Accept 创建一条新链接实际上是收到一条读事件,接下来咱们经过抓包来分析创建三次握手时时怎么样让 Nginx 收到读事件,使用的抓包工具是 Wireshark。
首先咱们安装 Wireshark 软件,并对 Nginx 所在 IP 和端口进行抓包,而后访问页面,在 TCP 层主要说两件事情:
IP 层主要解决机器与机器之间怎样互相找到的问题。
三次握手也就是 windows 先向 Nginx 发送了一次 [SYN],那么相反的 Nginx 所在的服务器也会向 windows 发送一个 [SYN],这个时候 Nginx 是没有感知到的,由于这个链接仍是处于半打开的状态。直到这台 windows 服务器再次发送 [ACK] 到 Nginx 所在的服务器之上时,Nginx 所在的操做系统才会去通知 Nginx 咱们收到了一个读事件,这个读事件对应是创建一个新链接,因此此时 Nginx 应该调用 Accept 方法去创建一个新的链接。
以上咱们经过 Wireshark 抓包演示了正常的三次握手是怎么样引起一个读事件来使得 Nginx 去处理这样一个读事件来创建新的链接的。
这篇文章主要讲解了网络事件,并经过抓包来分析 Nginx 网络事件,这对咱们理解 Nginx 异步处理框架是很是有帮助的,包括 OpenResty 也是强依赖于网络事件以及事件分发的。