Nginx极客时间:Nginx的模块究竟是什么

Nginx之所以有如此多的特性,是因为有大量的开发者在为其开发第三方模块,Nginx的模块化设计架构非常优良,那么究竟要如何表示一个模块?


1. Nginx模块是怎么定义的:

在这里插入图片描述

Nginx对模块做了高度抽象,每一个模块都用一个 ngx_module_t 结构体来表示:

typedef struct ngx_module_s ngx_module_t;

struct ngx_module_s {
	ngx_uint_t		ctx_index;					//本模块在同类型模块中的序号(如在http类型或event类型中的序号,默认为-1)
	ngx_uint_t		index;						//本模块在所有模块中的序号。如果某个模块跟其他模块的功能是冲突的, 那么先生效的模块会阻碍后生效的模块发挥作用
	
	char			*name;						//模块的名字,字符串,默认为空指针
	
	ngx_uint_t		spare0;						//保留字段
	ngx_uint_t		spare1;						//保留字段
	
	ngx_uint_t		version;					//nginx.h: #define nginx_version 1010000
	const char		*signature;					//模块的二进制兼容性签名:NGX_MODULE_SIGNATURE
	//以上以几个变量可以使用 NGX_MODULE_V1初始化:
	//#define NGX_MODULE_V1 0,0,0,0,0,0,1	

	void			*ctx;						//指向细分的子模块类型的结构体,如 &ngx_http_module_t, &ngx_event_module_t, &ngx_core_module_t 等
	ngx_command_t	*commands;					//模块所支持的指令,数组形式
	ngx_uint_t		type;						//本模块所属子模块的类型标识,如 NGX_HTTP_MODULE, NGX_EVENT_MODULE, NGX_CORE_MODULE, NGX_CONF_MODULE, NGX_MAIL_MODULE, NGX_STREAM_MODULE,目前共有6种

	//以下7个函数会在进程的启动或者结束阶段被调用,也就是说任何一个第三方模块都有机会在master进程 或 worker进程 的启动 或 退出时加载自己的代码:
	ngx_int_t		(*init_master)(ngx_log_t *log);			//目前Nginx不会调用 init_master
	ngx_int_t		(*init_module)(ngx_cycle_t *cycle);		//在master进程fork出worker进程之前被调用,做一些基本的初始化工作,数据会被子进程复制
	ngx_int_t		(*init_process)(ngx_cycle_t *cycle);	//在worker进程进入工作循环之前被调用,初始化每个子进程自己专用的数据
	ngx_int_t		(*init_thread)(ngx_cycle_t *cycle);		//Nginx目前不支持线程,所以init_thread目前不会被调用
	ngx_int_t		(*exit_thread)(ngx_cycle_t *cycle);		//nginx目前不支持线程,所以exit_thread目前不会被调用
	ngx_int_t		(*exit_process)(ngx_cycle_t *cycle);	//worker进程退出前调用
	ngx_int_t		(*exit_master)(ngx_cycle_t *cycle);		//master进程退出前调用
	
	//以下8个成员目前Nginx不会调用,使用 NGX_MODULE_V1_PADDING 填充
	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;
	
};


其中,ngx_command_t 结构体用于定义 Nginx 指令:

typedef struct ngx_command_s ngx_command_t;

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;				//专门给 http/stream 模块使用,决定存储在 main/server/loaction 哪个层次,其他模块不使用
	ngx_uint_t		offset;				//主要用于ngxin内置的命令解析函数,自定义的命令解析函数可以置为0。用于表示变量在conf结构体中的偏移量
	void			*post;				//解析后处理的数据
	
};

#define ngx_null_command { ngx_null_string, 0, NULL, 0, 0, NULL }	
//空指令,用于在指令数组的最后当做哨兵,结束数组,避免ngx_command_t[] 指定长度。类似于'\0'的结束字符串的作用



2. 定义一个Nginx第三方模块举例:

//ngx_http_pagecount_module.c
//定义一个 ngx_http_count_module 模块:

#include <ngx_http.h>
#include <ngx_config.h>
#include <ngx_core.h>

static char *ngx_http_count_module_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
	//do something ...
	//ngx_http_count_module_set作为 "count" 指令的回调解析函数
}

static ngx_http_module_t count_ctx {
	NULL,
	NULL,

	NULL,
	NULL,

	NULL,
	NULL,

	NULL,
	NULL,
};


static ngx_command_t count_commands[] = {
	{
		ngx_string("count"),
		NGX_HTTP_LOC_CONF | NGX_CONF_NOARGS,
		ngx_http_count_module_set,
		NGX_HTTP_LOC_CONF_OFFSET,
		0,
		NULL
	},
	
//	{
//		ngx_string("another_command"),
//		...
//	},
	
	ngx_null_command
};

ngx_module_t ngx_http_count_module {
	NGX_MODULE_V1,
	
	&count_ctx,
	count_commands,
	NGX_HTTP_MODULE,
	
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,

	NGX_MODULE_V1_PADDING
};

对应的配置文件可写成:


http {

	server {
		location /count {
			count;		#我们所定义的第三方模块中提供的指令
		}
	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值