本节我们介绍auto/modules脚本,该脚本的主要功能是定义Nginx相应的各个模块:
- event模块
- HTTP模块
- CORE模块
- HTTP_FILTER模块
- HTTP_INIT_FILTER模块
- HTTP_AUX_FILTER模块
- MAIL模块
- STREAM模块
- MISC模块
上述是几个大的模块类型,每一个模块类型里面可能会有多个小的子模块组成。其中后边8种模块
是ngx_module_type可取的类型。
1. auto/modules脚本
2. event模块
1) 首先判断EVENT_SELECT
有没有被设置,并且是否EVENT_FOUNT
变量是否找到了更先进的事件模型。如果两者都为否的话,则直接设置EVENT_SELECT=YES
,从这里我们可以看出nginx做的很聪明,它会先检查是否有更高级的事件模型,没有的话才会选择大部分系统都自持的相对来说性能较低的select模型。
默认情况下,在auto/options脚本中将EVENT_SELECT设置为了NO。
对于EVENT_FOUND,首先我们在auto/options脚本中初始设置为NO。然后在auto/os/linux脚本中对epoll
事件模型做了检测,接着在auto/unix脚本中对/dev/poll模型做了检测,后面又在auto/unix脚本中对
kqueue模型做了检测。
这里我们发现存在一个问题,对于中等效率的poll模型,其并没有通过EVENT_FOUND这一变量来指示。
但是nginx引入了另外一个变量EVENT_POLL,其首先在auto/options脚本中被设置为NO,然后在auto/unix
脚本中对poll模型进行检测,如果没有发现poll模型,则将EVENT_POLL设置为NONE。因此只要EVENT_POLL没有
被设置为NONE,就说明本身操作系统是支持poll模型的.
2) 接着判断EVENT_POLL
是否被设置,并且是否EVENT_FOUND
找到了更高级的事件模型。如果两者都为NO的话,则直接将EVENT_POLL
设置为YES。这是因为我们在上面已经讲到,如果系统本身不支持poll模型的话,EVENT_POLL
会被设置为NONE
,因此这里我们这样设置是没有问题的。
从这里我们可以看到对event模块的事件处理模型的选择,主要是通过EVENT_SELECT
,EVENT_POLL
,EVENT_FOUND
这三个变量控制的。则三个变量可以确保nginx能找到一个当前系统所支持的最先进的事件模型.
3) 最后再对三种先进的事件模型进行处理。分别判断如下三个变量是否被设置:
NGX_TEST_BUILD_DEVPOLL
NGX_TEST_BUILD_EVENTPORT
NGX_TEST_BUILD_EPOLL
默认情况下这三个变量都被设置为NO
,一般是用户明确你当前系统支持相应特性时可以显示通过如下参数进行设置:
--test-build-devpoll
--test-build-eventport
--test-build-epoll
否则一般情况下,应该让系统自己检测然后选择使用哪一种事件模型。
从如上脚本我们看到,发现相应的事件模型后,其都是定义好对应的宏定义;然后在往CORE_SRCS
,CORE_MODULES
添加相应的源文件及对应的事件模块名。
3. Solaris sendfilev特性
如果显示设置了NGX_TEST_BUILD_SOLARIS_SENDFILEV
,则将对应的源代码文件加入到CORE_SRCS变量中保存起来。
4. HTTP模块
首先将HTTP_MODULES
,HTTP_DEPS
,HTTP_INCS
都置为空,然后将ngx_module_type变量置为HTTP
。
接着设置HTTP
模块所需要的源文件、头文件、库文件等,调用auto/module脚本将相应的信息设置到模块变量中。
然后再执行如下:
默认情况下,HTTP
在auto/options中被置为YES
.
执行如下处理HTTP_CACHE
:
HTTP_CACHE
默认在auto/options中被设置为YES
,即启用缓存。
执行如下:
默认情况下,HTTP_SSI
被设置为YES
;而HTTP_SLICE
与HTTP_ADDITION
被设置为NO
。
5. HTTP_FILTER模块
1) 初始化相关变量
这里将ngx_module_type初始化为HTTP_FILTER
,HTTP_FILTER_MODULES
被初始化为空。
2) 定义ngx_module_order
这是因为在auto/options中,如下几个module都有可能会被设置为dynamic:
- HTTP_XSLT
- HTTP_IMAGE_FILTER
- HTTP_GEOIP
- HTTP_PERL
- MAIL
- STREAM
因此在下面有可能会处理这些模块时,首先定义好ngx_module_order。
3) 处理ngx_http_write_filter_module
ngx_http_write_filter_module作为内部静态模块处理。
4) 处理ngx_http_header_filter_module
ngx_http_header_filter_module作为内部静态模块处理。
5) 处理ngx_http_chunked_filter_module
ngx_http_chunked_filter_module作为内部静态模块处理。
6) 处理ngx_http_v2_filter_module
默认情况下HTTP_V2
被设置为NO
. HTTP_V2
主要用于提供对http/2的支持。
参看:Module ngx_http_v2_module
7) 处理ngx_http_range_header_filter_module
ngx_http_range_header_filter_module作为内部静态模块处理。
8) 处理ngx_http_gzip_filter_module
auto/options中默认会启用HTTP_GZIP
压缩。
9) 处理ngx_http_postpone_filter_module
上面我们提到这里HTTP_POSTPONE
会被置为YES
,因此会启用postpone filter模块。
10) 处理ngx_http_ssi_filter_module
默认情况下HTTP_SSI
会被置为YES
,因此这里会启用ssi filter模块。
11) 处理ngx_http_charset_filter_module
默认情况下HTTP_CHARSET
会被置为YES
,因此这里会启用charset filter模块。
12) 处理ngx_http_xslt_filter_module
在auto/options中HTTP_XSLT
默认被设置为NO
,但其可以通过如下:
--with-http_xslt_module) HTTP_XSLT=YES ;;
--with-http_xslt_module=dynamic) HTTP_XSLT=DYNAMIC ;;
来设置编译为内部静态模块
或外部动态模块
。
13) 处理ngx_http_image_filter_module
在auto/options中HTTP_IMAGE_FILTER
默认被设置为NO
,但是其可以通过如下:
--with-http_image_filter_module) HTTP_IMAGE_FILTER=YES ;;
--with-http_image_filter_module=dynamic)
HTTP_IMAGE_FILTER=DYNAMIC ;;
来设置编译为内部静态模块
或外部动态模块
.
14) 处理ngx_http_sub_filter_module
在auto/options脚本中HTTP_SUB
默认被设置为NO
。
15) 处理ngx_http_addition_filter_module
在auto/options脚本中HTTP_ADDITION
默认被设置为NO
.
16) 处理ngx_http_gunzip_filter_module
在auto/options脚本中HTTP_GUNZIP
默认被设置为NO
。
17) 处理ngx_http_userid_filter_module
在auto/options脚本中HTTP_USERID
默认被设置为YES
。
18) 处理ngx_http_headers_filter_module
ngx_http_headers_filter_module作为内部静态模块处理.
6. HTTP_INIT_FILTER模块
1) 初始化相关变量
这里将ngx_module_type初始化为HTTP_INIT_FILTER
,HTTP_INIT_FILTER_MODULES
被初始化为空。
2) 处理ngx_http_copy_filter_module
ngx_http_copy_filter_module作为内部静态模块处理。
3) 处理ngx_http_range_body_filter_module
ngx_http_range_body_filter_module作为内部静态模块处理。
4) 处理ngx_http_not_modified_filter_module
ngx_http_not_modified_filter_module作为内部静态模块处理。
5) 处理ngx_http_slice_filter_module
在auto/options脚本中HTTP_SLICE
默认被设置为NO
。
7. HTTP模块(续)
1) 初始化相关变量
将ngx_module_type初始化为HTTP
。
2) 处理ngx_http_v2_module
在auto/options脚本中HTTP_V2
默认设置为NO
.
3) 处理ngx_http_static_module
ngx_http_static_module作为内部静态模块处理.
4) 处理ngx_http_gzip_static_module
在auto/options脚本中,HTTP_GZIP_STATIC
默认被设置为NO
。
5) 处理ngx_http_dav_module
在auto/options脚本中,HTTP_DAV
默认被设置为NO
。
6) 处理ngx_http_autoindex_module
在auto/options脚本中,HTTP_AUTOINDEX
默认被设置为YES
。
7) 处理ngx_http_index_module
ngx_http_index_module作为内部静态模块处理。
8) 处理ngx_http_random_index_module
在auto/options脚本中,HTTP_RANDOM_INDEX
默认被设置为NO
。
9) 处理ngx_http_auth_request_module
在auto/options脚本中,HTTP_AUTH_REQUEST
默认被设置为NO
。
10) 处理ngx_http_auth_basic_module
在auto/options脚本中,HTTP_AUTH_BASIC
默认被设置为YES
.
11) 处理ngx_http_access_module
在auto/options脚本中,HTTP_ACCESS
默认被设置为YES
。
12) 处理ngx_http_limit_conn_module
在auto/options脚本中,HTTP_LIMIT_CONN
默认被设置为YES
。
13) 处理ngx_http_limit_req_module
在auto/options脚本中,HTTP_LIMIT_REQ
默认被设置为YES
。
14) 处理ngx_http_realip_module
在auto/options脚本中,HTTP_REALIP
默认被设置为NO
。
15) 处理ngx_http_status_module
在auto/options脚本中,HTTP_STATUS
默认被设置为NO
。
16) 处理ngx_http_geo_module
在auto/options脚本中,HTTP_GEO
默认被设置为YES
。
17) 处理ngx_http_geoip_module
在auto/options脚本中,HTTP_GEOIP
默认被设置为NO
。
18) 处理ngx_http_map_module
在auto/options脚本中,HTTP_MAP
默认被设置为YES
。
19) 处理ngx_http_split_clients_module
在auto/options脚本中,HTTP_SPLIT_CLIENTS
默认被设置为YES
。
20) 处理ngx_http_referer_module
在auto/options脚本中,HTTP_REFERER
默认被设置为YES
。
21) 处理ngx_http_rewrite_module
在auto/options脚本中,HTTP_REWRITE
默认被设置为YES
,USE_PCRE
默认被设置为NO
。
22) 处理ngx_http_ssl_module
在auto/options脚本中,HTTP_SSL
默认被设置为NO
。
23) 处理ngx_http_proxy_module
在auto/options脚本中,HTTP_PROXY
默认被设置为YES
。
24) 处理ngx_http_fastcgi_module
在auto/options脚本中,HTTP_FASTCGI
默认被设置为YES
。
25) 处理ngx_http_uwsgi_module
在auto/options脚本中,HTTP_UWSGI
默认被设置为YES
。
26) 处理ngx_http_scgi_module
在auto/options脚本中,HTTP_SCGI
默认被设置为YES
。
27) 处理ngx_http_perl_module
在auto/options脚本中,HTTP_PERL
默认被设置为NO
。
28) 处理ngx_http_memcached_module
在auto/options脚本中,HTTP_MEMCACHED
默认被设置为YES
。
29) 处理ngx_http_empty_gif_module
在auto/options脚本中,HTTP_EMPTY_GIF
默认被设置为YES
。
30) 处理ngx_http_browser_module
在auto/options脚本中,HTTP_BROWSER
默认被设置为YES
。
31) 处理ngx_http_secure_link_module
在auto/options脚本中,HTTP_SECURE_LINK
默认被设置为NO
。
32) 处理ngx_http_degradation_module
在auto/options脚本中,HTTP_DEGRADATION
默认被设置为NO
。
33) 处理ngx_http_flv_module
在auto/options脚本中,HTTP_FLV
默认被设置为NO
。
34) 处理ngx_http_mp4_module
在auto/options脚本中,HTTP_MP4
默认被设置为NO
.
35) 处理ngx_http_upstream_hash_module
在auto/options脚本中,HTTP_UPSTREAM_HASH
默认被设置为YES
。
36) 处理ngx_http_upstream_ip_hash_module
在auto/options脚本中,HTTP_UPSTREAM_IP_HASH
默认被设置为YES
。
37) 处理ngx_http_upstream_least_conn_module
在auto/options脚本中,HTTP_UPSTREAM_LEAST_CONN
默认被设置为YES
。
38) 处理ngx_http_upstream_keepalive_module
在auto/options脚本中,HTTP_UPSTREAM_KEEPALIVE
默认被设置为YES
。
39) 处理ngx_http_upstream_zone_module
在auto/options脚本中,HTTP_UPSTREAM_ZONE
默认被设置为YES
。
40) 处理ngx_http_stub_status_module
在auto/options脚本中,HTTP_STUB_STATUS
默认被设置为NO
。
7. MAIL模块
1) 处理MAIL模块
在auto/options脚本中,MAIL
默认被初始化为NO
。所以如下MAIL
模块其实并不会执行.
2) 初始化相关变量
3) 处理ngx_mail_module
ngx_mail_module作为内部静态模块处理。
4) 处理ngx_mail_ssl_module
在auto/options脚本中,MAIL_SSL
默认被初始化为NO
.
注意:ngx_module_incs被初始化为空
5) 处理ngx_mail_pop3_module
在auto/options脚本中,MAIL_POP3
默认被初始化为YES
。
注意:ngx_module_incs被初始化为空
6) 处理ngx_mail_imap_module
在auto/options脚本中,MAIL_IMAP
默认被初始化为YES
.
注意:ngx_module_incs被初始化为空
7) 处理ngx_mail_smtp_module
在auto/options脚本中,MAIL_SMTP
默认被初始化为YES
。
注意:ngx_module_incs被初始化为空
8) ngx_mail_auth_http_module
ngx_mail_auth_http_module作为内部静态模块处理。
注意:ngx_module_incs被初始化为空
9) 处理ngx_mail_proxy_module
ngx_mail_proxy_module作为内部静态模块处理。
注意:ngx_module_incs被初始化为空
8. STREAM模块
1) 处理STREAM模块
在auto/options脚本中,STREAM
默认被设置为NO
,所以如下STREAM
模块其实并不会被执行。
2) 初始化相关便利
3) 处理ngx_stream_module
ngx_stream_module作为内部静态模块处理。
4) 处理ngx_stream_ssl_module
在auto/options脚本中,STREAM_SSL
默认被初始化为NO
。
注意:ngx_module_incs被初始化为空
5) 处理ngx_stream_limit_conn_module
在auto/options脚本中,STREAM_LIMIT_CONN
默认被初始化为YES
。
注意:ngx_module_incs被初始化为空
6) 处理ngx_stream_access_module
在auto/options脚本中,STREAM_ACCESS
默认被初始化为YES
。
注意:ngx_module_incs被初始化为空
7) 处理ngx_stream_upstream_hash_module
在auto/options脚本中,STREAM_UPSTREAM_HASH
默认被初始化为YES
.
注意:ngx_module_incs被初始化为空
8) 处理ngx_stream_upstream_least_conn_module
在auto/options脚本中,STREAM_UPSTREAM_LEAST_CONN
默认被初始化为YES
。
注意:ngx_module_incs被初始化为空
9) 处理ngx_stream_upstream_zone_module
在auto/options脚本中,STREAM_UPSTREAM_ZONE
默认被初始化为YES
。
注意:ngx_module_incs被初始化为空
9. 处理外部静态模块(ADDONS)
由于我们并没有设置NGX_ADDONS
,因此本段脚本其实并不会被执行。这里我们简单分析一下脚本:首先遍历NGX_ADDONS
,将ngx_module_link置为ADDON
,然后调用对应目录下的config脚本文件。
例如,我们有ngx_http_hello_world_module,其config一般类似于如下:
10. 处理外部动态加载模块(DYNAMIC ADDONS)
由于我们并没有设置DYNAMIC_ADDONS
,因此本段脚本其实并不会被执行。关于脚本的分析与上述“处理外部静态模块(ADDONS)”类似,这里不再赘述。
11. 处理CORE_MODULES
CORE_MODULES
在auto/sources中被初始化为:
CORE_MODULES="ngx_core_module ngx_errlog_module ngx_conf_module"
它是属于Nginx框架最核心、最基础的模块。我们后续分析时也会首要分析这三个模块。
1) 处理ngx_openssl_module
在auto/options脚本中,USE_OPENSSL
默认被初始化为NO
,但是因为我们SSL的开启还会受到如下三个模块的影响:
- HTTP_SSL
- MAIL_SSL
- STREAM_SSL
这里我们在执行congfigure脚本时通过--with-http_ssl_module
选项启用了http ssl,因此也会自动使能USE_OPENSSL
,从而将ngx_openssl_module模块也纳入到核心模块中。
2) 处理ngx_regex_module
这里我们在执行configure脚本时通过--with-pcre
选项启用了pcre,因此USE_PCRE
的值为YES
,从而将ngx_regex_module纳入到核心模块之中。
12. 合并MODULES模块
前面我们提到的ngx_module_type
所支持的8种模块,我们已经处理完成了其中7种(还有MISC
模块未介绍),这里我们先对这些模块进行合并。
1) 初始化modules
2) 处理THREAD_POOL_MODULE
在auto/options脚本中,USE_THREADS
默认被初始化为NO
,因此这里其实并不会被执行。THREAD_POOL_MODULE
其实是与EVENT_MODULE
类似,其在auto/sources脚本中被设置为:
THREAD_POOL_MODULE=ngx_thread_pool_module
但是最终并不会被加入到编译源代码中。
3) 合并HTTP相关的模块
4) 合并MAIL相关模块
在auto/options脚本中,MAIL
默认被初始化为NO
,所以如下MAIL
模块其实并不会执行,但是我们来分析一下DYNAMIC
的情形:
MAIL
模块代表着整邮件模块,其中包含几个子模块。在MAIL
模块内部是以ngx_module_link=YES
链接在一起的,但是作为MAIL
模块整体其可以作为外部动态加载模块来工作的,因此这里会有如上elif分支。
5) 合并STREAM相关模块
在auto/options脚本中,MSTREAMAIL
默认被初始化为NO
,所以如下STREAM
模块其实并不会执行。其他与上面MAIL
模块合并类似,这里不再赘述。
13. MISC模块
到此为止,我们上面说的8大模块中就只剩下这里要介绍的MISC
模块了:
1) 初始化相关变量
2) 处理ngx_google_perftools_module
在auto/options脚本中,NGX_GOOGLE_PERFTOOLS
默认被初始化为NO
。perftools模块主要是用于相应的性能分析。
3) 处理test module
本模块其实ngx_module_name为空,并没有为其命名。其主要用于对nginx相关模块的一个测试。
4) 合并MISC模块
上面 第12节 我们提到了模块的合并,这里也对MISC
模块进行合并。
14. 生成ngx_modules.c文件
在前面我们已经合并了所有的MODULES
,此时遍历这些模块,然后生成ngx_modules.c文件:
整个脚本比较简单,NGX_PRAGMA
对于我们的当前的环境来说为空,生成的脚本基本样式如下:
extern ngx_module_t $mod;
ngx_module_t *ngx_modules[] = {
};
char *ngx_module_names[] = {
NULL
};
下面我们给出当前我们配置所生成的objs/ngx_modules.c源文件:
ngx_modules.c文件就是用来定义ngx_modules数组的。
ngx_modules是非常关键的数组,它指明了每个模块在Nginx中的优先级,当一个请求同时符合多个模块的处理规则时,它将按照它们在ngx_modules数组中的顺序选择最靠前的模块优先处理。对于HTTP过滤模块而言则相反,因为HTTP框架在初始化时,会在ngx_modules数组中将过滤模块按先后顺序向过滤链表中添加,但每次都添加到链表表头,因此,对HTTP过滤模块而言,在ngx_modules数组中越靠后的模块反而会首先处理HTTP响应。
因此,ngx_modules中模块的先后顺序非常重要,不正确的顺序会导致nginx无法工作,上面是auto/modules脚本执行后的结果。可以体会一下上面的ngx_modules中同一类型下各个模块的顺序以及这种顺序带来的意义。