ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 一文带你解析 Nginx 事件模型概念!

一文带你解析 Nginx 事件模型概念!

原创 Linux操作系统 作者:老男孩Linux 时间:2025-11-21 13:45:23 0 删除 编辑

  Nginx的事件模型

  1. WEB请求处理机制

  1.1 WEB服务器常用的处理请求方式

  多进程方式

  Apache 的 Prefork 模式就是多进程处理方式,当收到客户端的请求时,由服务器的主进程生成一个子进程来和该客户端进行交互。

  该方式的优势是各个进程之间相互隔离,保证的服务器的稳定性。但是缺点很明显,对服务器的资源,尤其是内存的消耗很大,进程之间的上下文切换太重量级了,不适合大并发的场景。

  异步方式

  •   同步和异步

  同步是指在发送方发出消息后,需要等待接收到接收方发回的响应,或者通过回调函数来接收到对方响应信息。

  异步是指在发送方发出请求后,接收方不返回消息或者不等待返回消息。

  通俗一点解释:

  同步:同步就是我买了一个烧水壶,烧水壶没有提供响应的机制,导致我不知道水啥时候开

  异步:异步就是我买了一个烧水壶,烧水壶提供了响应的机制,导致我可以知道水啥时候开

  •   阻塞和非阻塞

  在网络通讯中,阻塞和非阻塞主要是指Socket的阻塞和非阻塞方式,而socket的实质是IO操作。

  阻塞是指在IO操作返回结果之前,当前的线程处于被挂起状态,直到调用结果返回后才能处理其它新的请求。

  非阻塞指在IO操作返回结果之前,当前的线程会继续处理其它的请求。

  阻塞:和上面一样,我买了一个烧水壶,我要在旁边一直等着烧水壶开,这段时间,一点事情都没法做

  非阻塞:我买了一个烧水壶,在烧水的这段时间,我可以去做其他事情

  •   同步阻塞方式(常用,简单)

  发送方向接收方发送请求后,一直处理等待响应状态。接收方处理请求时进行IO操作,如果该操作没有立刻返回结果,将继续等待,直到返回结果后,才响应发送方,期间不能处理其它请求。

  同步阻塞:烧水壶没有提供响应机制,并且我要一直在旁边守着,等待水壶烧开

  同步非阻塞:烧水壶没有提供响应机制,但是我可以在这段期间,去干点别的事情,比如看看电视啊,打打游戏啊,然后每隔一段时间去看一眼水壶是否烧开

  •   异步非阻塞(常用)

  发送方向接收方发送请求后,继续进行其它工作。接收方处理请求进行IO操作,如果没有立刻返回结果,将不再等待,而是处理其它请求。

  异步阻塞:烧水壶提供了响应机制,但是我在旁边一直守着,等着水壶开

  异步非阻塞:烧水壶提供了响应机制,并且我可以在这段时间内,去干点别的事情

  1.2 Nginx服务器处理请求的方式

  Nginx的异步非阻塞

  Nginx 在服务启动后会产生一个主进程(master process)、多个工作进程(worker processes)、缓存加载进程(cache load processes)、缓存管理进程(cache manager processes),工作进程用于接收和处理客户端请求。

  每个工作进程使用了异步非阻塞的方式,可以处理多个客户端的请求。当某个工作进程接收到客户端的请求后,使用事件驱动方式管理socket,将socket设置为非阻塞方式。

  在涉及IO操作时,可以调用Linux文件系统提供的AIO接口,使用异步IO方式完成调用,针对任务繁重的IO操作可以将等待IO的操作卸载给线程池中其它线程处理,从而避免主线程(worker进程的主循环)阻塞。

  Nginx处理请求的过程

  2. 事件驱动模型

  Nginx管理socket的方式称为事件驱动模型。

  2.1 SELECT 库

POSIX所规定,目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点,本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理。
缺点:
单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024,可以通过修改宏定义FD_SERSIZE,再重新编译内核实现,但是这样也会造成效率的降低
单个进程可监视的fd数量被限制,默认是1024,修改此值需要重新编译内核
对socket是线性扫描,即采用轮询的方法,效率较低
select采取了内存拷贝方法来实现内核将FD消息通知给用户空间,这样一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大。

  2.2 POLL 库

poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态
其没有最大连接数的限制,原因是它是基于链表来存储的
大量的fd的数组被整体复制于用户态和内核地址空间之间,而不管这样的复制是不是有意义
poll特点是“水平触发”,如果报告了fd后,没有被处理,那么下次poll时会再次报告该fd
select是边缘触发即只通知一次

  2.3 EPOLL库

无论是SELECT还是POLL事件驱动模型,都是需要使用轮询的方法检查连接是否有新的事件,在连接数非常多的时候,轮询会非常消耗性能。
Epoll库是Linux高性能事件驱动模型库,其效率远超poll和select库。Linux 2.6及以上的版本都可以使用。
首先,当有新的socket连接时,nginx使用epoll库创建与socket相关联的文件描述符,并设置需要关注的事件,并将其添加到内核事件列表中。
然后,epoll库等待内核通知即可。省掉了select和poll库中轮询文件描述符的步骤。
Epoll库支持一个进程打开最大数目的事件描述符,上限是系统可以打开文件的最大数目;同时epoll库的IO效率不随文件描述符的增加而线性下降,因为它只会对内核上报的"活跃的描述符进行操作。#最大并发连接数,此值和系统内存大小有关,内存多大,那么最大连接数,就可以有多大[root@nginx-01 ~]# free -h
              total        used        free      shared  buff/cache   available
Mem:           1.8G        124M        403M        8.7M        1.3G        1.4G
Swap:          2.0G          0B        2.0G[root@nginx-01 ~]# cat /proc/sys/fs/file-max 181976

  2.4 常用I/O模型比较

  3. Nginx的进程

  3.1 进程的分类

  master process

  Nginx启动时运行的主要进程,主要功能如下

  •   读取Nginx配置文件并验证其有效性和正确性
  •   建立、绑定、关闭socket连接
  •   按照配置生成、管理进程和结束工作进程
  •   接收外界指令,如重启、退出等
  •   不中断服务,实现平滑升级,重启服务并应用新的配置
  •   编译和处理Perl脚本
  •   开启日志记录

  worker processes

  •   接收并处理客户端请求
  •   将请求以此送入各个功能模块进行处理
  •   IO调用,获取响应数据
  •   与后端服务器通信,接收后端服务器的处理结果
  •   缓存数据,访问缓存索引,查询和调用缓存数据
  •   发送请求结果,响应客户的请求
  •   接收主程序的指令

  cache loader

  在开启缓存服务器功能下,在Nginx主进程启动一段时间后(默认1分钟),由主进程生成cache loader,在缓存索引建立完成后将自动退出。

  Cache Manager

  在开启缓存服务器功能下,在Nginx主进程的整个生命周期内,管理缓存索引,主要对索引是否过期进程判断。

  3.2 进程之间的交互

  主进程与工作进程的交互

  ⼯作进程是有主进程⽣成的,主进程使⽤fork()函数,在Nginx服务器启动过程中主进程根据配置⽂件决定启动⼯作进程的数量,然后建⽴⼀张全局的⼯作表⽤于存放当前未退出的所有的⼯作进程,主进程⽣成⼯作进程后会将新⽣成的⼯作进程加⼊到⼯作进程表中,并建⽴⼀个单向的管道并将其传递给⼯作进程,该管道与普通的管道不同,它是由主进程指向⼯作进程的单项通道,包含了主进程向⼯作进程发出的指令、⼯作进程ID、⼯作进程在⼯作进程表中的索引和必要的⽂件描述符等信息。主进程与外界通过信号机制进⾏通信,当接收到需要处理的信号时,它通过管道向相关的⼯作进程发送正确的指令,每个⼯作进程都有能⼒捕获管道中的可读事件,当管道中有可读事件的时候,⼯作进程就会从管道中读取并解析指令,然后采取相应的执⾏动作,这样就完成了主进程与⼯作进程的交互。

  工作进程与工作进程的交互

  ⼯作进程之间的通信原理基本上和主进程与⼯作进程之间的通信是⼀样的,只要⼯作进程之间能够取得彼此的信息,建⽴管道即可通信,但是由于⼯作进程之间是完全隔离的,因此⼀个进程想要直到另外⼀个进程的状态信息就只能通过主进程来设置了。

  为了实现⼯作进程之间的交互,主进程在⽣成⼯作进程之后,在⼯作进程表中进⾏遍历,将该新进程的ID以及针对该进程建⽴的管道句柄传递给⼯作进程中的其他进程,为⼯作进程之间的通信做准备,当⼯作进程1向⼯作进程2发送指令的时候,⾸先在主进程给它的其他⼯作进程⼯作信息中找到2的进程ID,然后将正确的指令写⼊指向进程2的管道,⼯作进程2捕获到管道中的事件后,解析指令并进⾏相关操作,这样就完成了⼯作进程之间的通信。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69952968/viewspace-3102806/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
老男孩it教育——致力于帮助有志向的年轻人通过努力学习获得体面的工作和生活。专注于Linux云计算运维、Python全栈开发、网络安全、新媒体运营、容器云架构师、MySQL数据库、go语言的培训。学习可call:18710030740

注册时间:2019-11-06

  • 博文量
    389
  • 访问量
    1010483