Author: haoransun
Wechat: SHR—97
学习来源:极客时间-Nginx核心知识100讲,本人购买课程后依据视频讲解汇总成个人见解。
前言
Nginx是一个事件驱动的框架。事件主要指的是网络事件。Nginx每个连接会自然对应两个网络事件,读事件 与 写事件。因此,我们在深入了解Nginx的各种原理以及它在极端场景下的各种错误处理时,必须首先理解什么是网络事件。
网络收发
网络传输
TCP流与报文
TCP协议与非阻塞接口
Nginx网络事件实例演示
访问 116.62.160.193:8080 这是一个之前搭建的Nginx-Web静态资源服务器.
同时要安装 Wireshark网络抓包器。
TCP三次握手时会发送 SYN、SYN+ACK、ACK包
TCP层主要是做进程与进程间的通讯,本地打开1875端口,远程是8080端口
IP层主要解决机器之间互相找到的问题。本地IP是 192.168.74.142,远端Nginx所在IP是 116.62.160.193
Nginx事件驱动模型
在了解了网络事件以及事件分发、收集器后,再来学习Nginx是如何处理事件的。
Nginx事件循环
流程:
当Nginx刚刚启动时,处于 WAIT FOR EVENTS ON CONNECTIONS状态,即我们打开了80、443端口后,等待新的事件进来(如新的客户端连上了Nginx,向我们发起了连接)。这一步对应着 epoll中的 epoll_wait方法。Nginx是处于Sleep进程状态。
当操作系统收到了一个建立连接的TCP握手报文并处理完成后,操作系统就会通知epoll_wait阻塞方法,告之可以往下走了(找操作系统要事件),并且唤醒我们的Nginx-Worker进程。
Kernel 即操作系统内核会将事件放入到事件队列中。从事件队列中,Nginx可以获取到要处理事件,如 建立连接、TCP请求报文等。取出来后就会处理对应的事件,进入 PROCESS THE EVENTS QUEUE CIRCLE,即右边的图。
队列不为空,就将事件取出来进行处理。在处理事件的过程中可能会生成一些新的事件(如:新连接建立,要设置一个超时时间,超时时间后,浏览器不向我发送新的请求,我就关闭它。又比如:当收完完整的HTTP请求后,可以进行HTTP响应了,这个响应是需要我可以向操作系统的写缓存区中把响应写进来的,要求操作系统尽快把这样一段写的内容发回给浏览器,即期待一个写事件等等)。
所有的事件处理完成后,又会返回到 WAIT FOR EVENTS ON CONNECTIONS状态。
知道上述流程的好处:
一些第三方模块可能会做大量的CPU运算,此类计算任务会导致我处理一个事件的时间非常长,在上述流程图中会导致后续队列中的大量事件长时间得不到处理。从而引发恶性循环,他们的超时时间可能到了,CPU都消耗到处理连接不正常的断开。
有些第三方模块长时间的消耗大量CPU进行计算任务,这是Nginx不能容忍的。gzip等模块不会一次使用大量的CPU,而是分段使用。
epoll的优势及原理
上面讨论到了Nginx事件分发机制,最关键的就是Nginx怎样快速的从操作系统的Kernel中获取到等待处理的事件。这一步经历了很长时间的解决。当下Nginx主要是使用epoll网络事件收集器模型。
各个模型性能对比
epoll
Nginx请求切换场景使用epoll带来的争议
请求切换
传统服务依赖OS,处理大量连接时很困难。
Nginx用户态即可完成切换。除非Nginx-Worker时间片到了(5ms-800ms),才会依赖OS切换,因此往往将Nginx-Worker优先级加到最高(-19),操作系统分配的时间片往往是最大的。这样能比较好的在用户态完成进程切换,使得CPU少做无用功。
同步&异步 阻塞&非阻塞之间的区别
同步是两个对象之间的关系,而阻塞是一个对象的状态。
阻塞可以是实现同步的一种手段!例如两个东西需要同步,一旦出现不同步情况,我就阻塞快的一方,使双方达到同步。
阻塞调用
非阻塞调用
非阻塞调用下的同步与异步
四种组合方式
1 | 同步阻塞方式: |
1 | 同步非阻塞方式: |
1 | 异步阻塞方式: |
1 | 异步非阻塞方式: |