nginx 的一大设计亮点就是可拓展, 可插拔的模块化架构; 在使用的时候, 我们可以根据自己业务的需求选择合适的模块组合;
本文涉及的源码基于 nginx 1.11.2.4;
nginx 模块相关数据结构
各数据结构的别名
1 2 3 4 5
| typedef struct ngx_module_s ngx_module_t; typedef struct ngx_command_s ngx_command_t; typedef struct ngx_event_s ngx_event_t; typedef struct ngx_conf_s ngx_conf_t;
|
指令数据结构 ngx_command_t
用于定义模块拥有什么可以设置的 关键字/指令 (directive), 如 ngx_http_core_module 中的 user, pid, master_process 等;
1 2 3 4 5 6 7 8 9
| struct ngx_command_s { ngx_str_t name; ngx_uint_t type; char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); ngx_uint_t conf; ngx_uint_t offset; void *post; };
|
其中, 最重要的是第二个参数 type, 它是对以下两类 条件限定 作了一个 按位或 操作:
- 指令允许在哪些 context 中使用;
- 指令所接收的参数情况(参数形态, 参数个数);
对第一类条件, 限定的 context 上下文, 常用的类型如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #define NGX_MAIN_CONF 0x01000000 #define NGX_ANY_CONF 0x1F000000
#define NGX_HTTP_MAIN_CONF 0x02000000 #define NGX_HTTP_SRV_CONF 0x04000000 #define NGX_HTTP_LOC_CONF 0x08000000 #define NGX_HTTP_UPS_CONF 0x10000000 #define NGX_HTTP_SIF_CONF 0x20000000 #define NGX_HTTP_LIF_CONF 0x40000000 #define NGX_HTTP_LMT_CONF 0x80000000
#define NGX_EVENT_CONF 0x02000000
|
对第二类条件, 首先是参数形态, 可以有如下类型:
1 2 3
| #define NGX_CONF_BLOCK 0x00000100 #define NGX_CONF_FLAG 0x00000200 #define NGX_CONF_ANY 0x00000400
|
然后是参数数目:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #define NGX_CONF_NOARGS 0x00000001 #define NGX_CONF_TAKE1 0x00000002 #define NGX_CONF_TAKE2 0x00000004 #define NGX_CONF_TAKE3 0x00000008 #define NGX_CONF_TAKE4 0x00000010 #define NGX_CONF_TAKE5 0x00000020 #define NGX_CONF_TAKE6 0x00000040 #define NGX_CONF_TAKE7 0x00000080
#define NGX_CONF_1MORE 0x00000800 #define NGX_CONF_2MORE 0x00001000
#define NGX_CONF_TAKE12 (NGX_CONF_TAKE1|NGX_CONF_TAKE2) #define NGX_CONF_TAKE13 (NGX_CONF_TAKE1|NGX_CONF_TAKE3) #define NGX_CONF_TAKE23 (NGX_CONF_TAKE2|NGX_CONF_TAKE3) #define NGX_CONF_TAKE123 (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3) #define NGX_CONF_TAKE1234 (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3|NGX_CONF_TAKE4)
#define NGX_CONF_MAX_ARGS 8
|
上下文数据结构 ngx_module_ctx
大致分为以下几类: core, http, event, mail;
ngx_conf_module 没有对应的 module context;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| typedef struct { ngx_str_t name; void *(*create_conf)(ngx_cycle_t *cycle); char *(*init_conf)(ngx_cycle_t *cycle, void *conf); } ngx_core_module_t;
typedef struct { ngx_str_t *name; void *(*create_conf)(ngx_cycle_t *cycle); char *(*init_conf)(ngx_cycle_t *cycle, void *conf); ngx_event_actions_t actions; } ngx_event_module_t;
typedef struct { ngx_int_t (*preconfiguration)(ngx_conf_t *cf); ngx_int_t (*postconfiguration)(ngx_conf_t *cf); void *(*create_main_conf)(ngx_conf_t *cf); char *(*init_main_conf)(ngx_conf_t *cf, void *conf); void *(*create_srv_conf)(ngx_conf_t *cf); char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf); void *(*create_loc_conf)(ngx_conf_t *cf); char *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf); } ngx_http_module_t;
typedef struct { ngx_mail_protocol_t *protocol; void *(*create_main_conf)(ngx_conf_t *cf); char *(*init_main_conf)(ngx_conf_t *cf, void *conf); void *(*create_srv_conf)(ngx_conf_t *cf); char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf); } ngx_mail_module_t;
|
模块的类型
模块的类型都被定义为 无符号整型:
1 2 3 4 5 6 7 8 9 10 11 12
| #define NGX_HTTP_MODULE 0x50545448
#define NGX_CORE_MODULE 0x45524F43 #define NGX_CONF_MODULE 0x464E4F43
#define NGX_MAIL_MODULE 0x4C49414D
#define NGX_EVENT_MODULE 0x544E5645
|
模块定义数据结构 ngx_module_t
ngx_module_t 是 nginx module 的最终定义之处, 其中字段包括了上面提及的 ngx_module_ctx 上下文, ngx_command_t[] 可配置指令集, 模块的类型, 以及各种生命周期中的回调函数;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| struct ngx_module_s { ngx_uint_t ctx_index; ngx_uint_t index; char *name; ngx_uint_t spare0; ngx_uint_t spare1; ngx_uint_t version; const char *signature; void *ctx; ngx_command_t *commands; ngx_uint_t type; ngx_int_t (*init_master)(ngx_log_t *log); ngx_int_t (*init_module)(ngx_cycle_t *cycle); ngx_int_t (*init_process)(ngx_cycle_t *cycle); ngx_int_t (*init_thread)(ngx_cycle_t *cycle); void (*exit_thread)(ngx_cycle_t *cycle); void (*exit_process)(ngx_cycle_t *cycle); void (*exit_master)(ngx_cycle_t *cycle); uintptr_t spare_hook0; uintptr_t spare_hook1; uintptr_t spare_hook2; uintptr_t spare_hook3; uintptr_t spare_hook4; uintptr_t spare_hook5; uintptr_t spare_hook6; uintptr_t spare_hook7; };
|
常用于填充的两个宏定义如下:
1 2 3 4 5 6
|
#define NGX_MODULE_V1 NGX_MODULE_UNSET_INDEX, NGX_MODULE_UNSET_INDEX, NULL, 0, 0, nginx_version, NGX_MODULE_SIGNATURE #define NGX_MODULE_V1_PADDING 0, 0, 0, 0, 0, 0, 0, 0
|
nginx 模块加载与查看
模块加载的时机
nginx 模块是在静态编译时加载的, 无法如 apache 一般使用动态链接库加载, 编译时指定选项以加载指定模块:
1 2
| sudo /usr/local/nginx-1.11.2/configure --without-xxx_module --with-yyy_module sudo make && sudo make install
|
nginx 编译完成后, 在 objs/ 目录下会自动生成模块加载的源文件 ngx_modules.c
与目标文件 ngx_modules.o
:
1 2 3 4 5 6 7 8 9 10 11 12 13
| ngx_module_t *ngx_modules[] = { &ngx_core_module, &ngx_errlog_module, &ngx_conf_module, &ngx_openssl_module, &ngx_regex_module, &ngx_events_module, &ngx_event_core_module, &ngx_epoll_module, &ngx_http_module, &ngx_http_core_module, ... };
|
nginx 已加载模块的查看
1 2 3 4 5 6
| > /usr/local/nginx/sbin/nginx -V nginx version: openresty/1.11.2.4 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-4) (GCC) built with OpenSSL 1.0.1e-fips 11 Feb 2013 TLS SNI support enabled configure arguments: --prefix=/usr/local/openresty/nginx --with-cc-opt=-O2 --add-module=../ngx_devel_kit-0.3.0 --add-module=../echo-nginx-module-0.60 --add-module=../xss-nginx-module-0.05 --add-module=../ngx_coolkit-0.2rc3 --add-module=../set-misc-nginx-module-0.31 --add-module=../form-input-nginx-module-0.12 --add-module=../encrypted-session-nginx-module-0.06 --add-module=../srcache-nginx-module-0.31 --add-module=../ngx_lua-0.10.8 --add-module=../ngx_lua_upstream-0.06 --add-module=../headers-more-nginx-module-0.32 --add-module=../array-var-nginx-module-0.05 --add-module=../memc-nginx-module-0.18 --add-module=../redis2-nginx-module-0.14 --add-module=../redis-nginx-module-0.3.7 --add-module=../rds-json-nginx-module-0.14 --add-module=../rds-csv-nginx-module-0.07 --with-ld-opt=-Wl,-rpath,/usr/local/openresty/luajit/lib --with-http_gunzip_module --with-http_gzip_static_module --with-http_ssl_module
|
参考链接