模块结构

Nginx是一个高性能的HTTP和反向代理服务器,它由内核和模块组成

内核包含着一些基础的数据结构,例如:链表、内存池、hashmap、String等,内核的工作十分简单,只是负责查找配置文件映射到location block上,location上匹配的指令将会启动不同的模块进行工作

Nginx 的模块从结构上分为核心模块、基础模块和第三方模块

  • 核心模块:HTTP 模块、EVENT 模块和 MAIL 模块
  • 基础模块:HTTP Access 模块、HTTP FastCGI 模块、HTTP
  • 第三方模块:HTTP Upstream Request Hash 模块、Notice 模块和 HTTPAccess Key 模块

用户根据自己的需要开发的模块都属于第三方模块。正是有了这么多模块的支撑,Nginx 的功能才会如此强大。

Nginx 的模块从功能上分为如下三类:

  • Handlers:即处理器模块。此类模块直接处理请求,并进行输出内容和修改 headers 信息等操作。Handlers 处理器模块一般只能有一个。
  • Filters:即过滤器模块。此类模块主要对其他处理器模块输出的内容进行修改操作,最后由 Nginx 输出。
  • Proxies:即代理类模块。此类模块是 Nginx 的 HTTP Upstream 之类的模块,这些模块主要与后端一些服务比如 FastCGI 等进行交互,实现服务代理和负载均衡等功能。

进程模型

nginx进程模型

nginx启动后会创建一个master进程(建立需要listen的socket),Master进程再fork出若干个worker进程,当用户请求到nginx时,worker会接受并处理用户请求

master进程

master进程只负责管理worker进程,当master进程启动后,它会读取配置文件,fork出worker进程;当重新启动master进程时,它会重新加载配置文件,并启动新的worker进程,向旧的worke进程发送信号,结束旧进程,而旧的worker在收到来自master的信号后,就不再接收新的请求,并且在当前进程中的所有未处理完的请求处理完成后,再退出。

worker进程

worker进程之间是平等的,每个进程,处理请求的机会也是一样的。当我们提供80端口的http服务时,一个连接请求过来,每个进程都有可能处理这个连接。首先,每个worker进程都是从master进程fork过来,在master进程里面,先建立好需要listen的socket(listenfd)之后,然后再fork出多个worker进程。所有worker进程的listenfd会在新连接到来时变得可读,为保证只有一个进程处理该连接,所有worker进程在注册listenfd读事件前抢accept_mutex,抢到互斥锁的那个进程注册listenfd读事件,在读事件里调用accept接受该连接。当一个worker进程在accept这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接,这样一个完整的请求就是这样的了。我们可以看到,一个请求,完全由worker进程来处理,而且只在一个worker进程中处理。

多进程IO模型

Nginx 采用了异步非阻塞的方式来处理请求。也就是说,Nginx 是可以同时处理成千上万个请求的。非阻塞就是,事件没有准备好,马上返回EAGAIN,告诉你,事件还没准备好呢,你慌什么,过会再来吧。好吧,你过一会,再来检查一下事件,直到事件准备好了为止,在这期间,你就可以先去做其它事情,然后再来看看事件好了没,也就是epoll多路复用技术