🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 3.4 Nginx的模块化体系 ### 一、模块体系 Nginx的内部结构是由核心部分和一系列功能模块组成的,这样可以使得每个模块的功能相对简单,便于对系统进行功能扩展,各模块之间的关系如下图: ![](https://img.kancloud.cn/02/0a/020a8d474c270fdecdb59a1633901db4_227x227.png) nginx core实现了底层的通讯协议,为其它模块和Nginx进程构建了基本的运行时环境,并且构建了其它各模块的协作基础。 http模块和mail模块位于nginx core和各功能模块的中间层,这2个模块在nginx core之上实现了另外一层抽象,分别处理与http协议和email相关协议(SMTP/IMAP/POP3)有关的事件,并且确保这些事件能被以正确的顺序调用其它的一些功能模块。 nginx功能模块基本上分为如下几种类型: (1)event module:搭建了独立于操作系统的事件处理机制的框架,以及提供了各具体事件的处理,包括ngx_event_module、ngx_event_core_module和ngx_epoll_module等,Nginx具体使用何种事件处理模块,这依赖于具体的操作系统和编译选项。 (2)phase handler:此类型的模块也被直接称为handler模块,主要负责处理客户端请求并产生待响应内容,比如ngx_http_module模块,负责客户端的静态页面请求处理并将对应的磁盘文件准备为响应内容输出。 (3)output filter:也称为filter模块,主要是负责对输出的内容进行处理,可以对输出进行修改,比如可以实现对输出的所有html页面增加预定义的footbar一类的工作,或者对输出的图片的URL进行替换之类的工作。 (4)upstream:实现反向代理功能,将真正的请求转发到后端服务器上,并从后端服务器上读取响应,发回客户端,upstream模块是一种特殊的handler,只不过响应内容不是真正由自己产生的,而是从后端服务器上读取的。 (5)load-balancer:负载均衡模块,实现特定的算法,在众多的后端服务器中,选择一个服务器出来作为某个请求的转发服务器。 (6)extend module:根据特定业务需要编写的第三方模块。 ### 二、请求处理 下面将会以http请求处理为例来说明请求、配置和模块是如何串起来的。 当Nginx读取到一个HTTP Request的header时,首先查找与这个请求关联的虚拟主机的配置,如果找到了则这个请求将会经历以下几个阶段的处理(phase handlers): **NGX_HTTP_POST_READ_PHASE**:读取请求内容阶段 **NGX_HTTP_SERVER_REWRITE_PHASE**:Server请求地址重写阶段 **NGX_HTTP_FIND_CONFIG_PHASE**:配置查找阶段 **NGX_HTTP_REWRITE_PHASE**:Location请求地址重写阶段 **NGX_HTTP_POST_REWRITE_PHASE**:请求地址重写提交阶段 **NGX_HTTP_PREACCESS_PHASE**:访问权限检查准备阶段 **NGX_HTTP_ACCESS_PHASE**:访问权限检查阶段 **NGX_HTTP_POST_ACCESS_PHASE**:访问权限检查提交阶段 **NGX_HTTP_TRY_FILES_PHASE**:配置项try_files处理阶段 **NGX_HTTP_CONTENT_PHASE**:内容产生阶段 **NGX_HTTP_LOG_PHASE**:日志模块处理阶段 在内容产生阶段,为了给一个request产生正确的response,Nginx必须把这个请求交给一个合适的content handler去处理。如果这个request对应的location在配置文件中被明确指定了一个content handler,那么Nginx就可以通过对location的匹配,直接找到这个对应的handler,并把这个request交给这个content handler去处理。这样的配置指令包括perl、flv、proxy_pass、mp4等。 如果一个request对应的location并没有直接配置的content handler,那么Nginx依次作如下尝试: (1)如果一个location里面有配置random_index on,那么随机选择一个文件发送给客户端。 (2)如果一个location里面有配置index指令,那么发送index指令指定的文件给客户端。 (3)如果一个location里面有配置autoindex on,那么就发送请求地址对应的服务端路径下的文件列表给客户端。 (4)如果这个request对应的location上有设置gzip_static on,那么就查找是否有对应的.gz文件存在,如果有的话,就发送这个给客户端(客户端支持gzip的情况下)。 (5)请求的URI如果对应一个静态文件,static module就发送静态文件的内容到客户端。 内容产生阶段完成以后,生成的输出会被传递到filter模块去进行处理。filter模块也是与location相关的。所有的fiter模块都被组织成一条链。输出会依次穿越所有的filter,直到有一个filter模块的返回值表明已经处理完成。接下来就可以发送response给客户端了。