目录
1.Nginx的模块
设计优良,从2004年发布到现在,没有发生大的变化.
学习Nginx的模块的高明之处,我们在学习一个模块的时候要从以下方面来进行学习:
1.这个模块要被编进Nginx中,这个是前提;
2.这个模块提供了哪些配置项;
3.这个模块什么时候被使用(有些模块只要编进Nginx默认会被使用,有些模块必须使用配置项并正确配置时才会被使用);
4.这个模块提供了哪些变量.
模块说明的官方链接:
http://nginx.org/en/docs/
这里面Modules reference部分给出了每个模块的详细说明.
2.以GZIP模块为例说明学习方法
1.打开官方文档
http://nginx.org/en/docs/http/ngx_http_gzip_module.html
可以看到这个模块的:
(1)Example Configuration(配置示例);
(2)Directives(指令集合);
(3)Embedded Variables(内嵌变量).
2.可以通过编译和看源码的方式来进行进一步学习
在编译好之后:
/home/muten/module/nginx-1.13.7/objs目录下生成ngx_modules.c这个文件,
这个文件里面可以看到哪些模块被编译进Nginx.
Nginx的源码放在/home/muten/module/nginx-1.13.7/src/下.
查看gzip的代码中的指令:
/home/muten/module/nginx-1.13.7/src/http/modules/ngx_http_gzip_filter_module.c
搜索ngx_command_t可以看到一些指令集的说明,如果官网中有些指令或者其他项没有说明,我们
也可以通过查看源码的方式去进行一些探索.
NGX_CONF_FLAG --配置项的标志
NGX_CONF_TAKE1 --一个参数
NGX_CONF_TAKE2 --两个参数
NGX_CONF_1MORE --一个参数或多个参数
NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF --说明可用在这些模块下
3.Nginx模块的定义
Nginx的模块是如何划分成不同的子模块的?
源码路径下搜索:
find . -name "*h" | xargs grep "ngx_module_s"可以找到ngx_module_t的定义.
ngx_module_t是每个模块必须具备的数据结构,其中type定义了这个模块属于哪个类型的模块(仅列举出部分),
一共有的模块:
(1)core_module
(2)http_module
(3)event_module
(4)mail_conf_ctx
...
给出上面提到的几个模块的数据结构定义:
(1)typedef struct ngx_module_s ngx_module_t--通用基础模块
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;//抽象方法
};
(2)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_core_module_t;
(3)ngx_http_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;
(4)ngx_event_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;
(5)ngx_mail_conf_ctx_t
typedef struct {
void **main_conf;
void **srv_conf;
} ngx_mail_conf_ctx_t;
4.Nginx的模块划分
http_core_module --核心模块
http_conf_module --独立的,解析配置文件
核心模块中会有一类核心模块,比如events,http,mail,stream,它们本身也可以定义
出新的子类型模块,可以看出Nginx框架代码并没有定义http或者core业务,而是通过某些
core_module去定义出新的子类型模块.
Nginx的灵活性是非常强的,如果新出了一类应用,可以通过新增core_module来定义一个新
的模块.
所有事件处理的通用方法我们将它内聚为事件模块(NGINX_EVENT_MODULE),每一类模块中会有一些
通用的共性的部分,对通用的共性的部分,我们会加上core关键字,会把通用部分的功能写在里面,
比如说even_core,ngx_http_core_module,ngx_stream_core_module,我们基础数据结构中的
ngx_module_t的index成员变量会给这些module一个index,表示它的顺序,每个子类型中的所有的
event模块,http模块同样也是有顺序的.每一个core_module一定是排序第一的,因为它定义了
所有子类型模块共同具有的特性.
NGINX_HTTP_MODULE是最复杂的,ngx_http_core_module定义了许多特殊的规则,比如说当一个
http请求进入nginx模块的时候,我们就要为它生成相应,这个生成响应的模块就是请求处理模块,
当把响应发送给浏览器的时候,我们可能要对发送的内容做一些特定的处理(如发送css时可以做压
缩处理,由于信息熵变大,效率会有大幅提升;如发送图片,我们可以用image_filter模块做一些
图片的缩放和裁剪;响应过滤模块专注于把响应做二次处理),还有一个upstream模块,upstream模块是
上游模块,Nginx做正向或者反向代理的时候使用到此模块,专注于在一个请求的内部访问上游服务.
mail和upstream暂时不细说.
5.从源码看目录与子类型模块的对应关系
下面以http子模块作为例子来做出说明:
(一)
所有的框架代码及http_core_module都是放在/home/muten/module/nginx-1.13.7/src/http
这个目录下的;
(二)
官方提供的非框架的(可有可无的模块)放在/home/muten/module/nginx-1.13.7/src/http/modules
目录下,对于http的这些可用可无的模块,分成三类:
(1)处理请求模块(除了响filter模块和upstream模块以外的其他模块都是生成响应或为生成响应而工作的模块);
(2)响应过滤模块(有关键字filter);
(3)与上游服务器发生交互的模块(带有upstream关键字的),这些是在负载均衡或相关工作的.
其他如http,event,mail等子模块也是一样的道理.
当我们拿到一个第三方的新的模块的时候,我们可以首先看它属于哪一类模块,这一类模块会有一些共同
的特性,可以帮助我们理解新模块的作用.