读懂ngxin的http配置(1)

背景:

在开发功能灵活的Nginx模块时,需要从配置文件中获取特定的信息,不过,不需要再 编写一套读取配置的系统,Nginx已经为用户提供了强大的配置项解析机制,同时它还支持“- s reload”命令——在不重启服务的情况下可使配置生效

预读知识

例子:

http {
   test_str main;
   server {
        listen 80;
        test_str server80;
     location url1 {
        mytest;
        test_str loc1;
}
    location url2 {
        mytest;
        test_str loc2;
        }
}

server 
listen 8080;
test_str server8080;
     location /url3 {
     mytest;
     test_str loc3;
    }
}

}

总体解析:

1.test_str这个配置项在http块内出现的值为main,在监听80端口的 server块内test_str值为server80,该server块内有两个location由mytest模块处理的且每个location中又重新设置了test_str的值,分别为loc1和loc2

2.在这之后又定义 了监听8080端口的server块,并重定义test_str的值为server8080,这个server块内定义的一个 location也是由mytest模块处理的,而且这个location内再次重定义了test_str的值为loc3。

效果:

在这段很短的配置中,mytest模块将会处理两个监听端口上建立的TCP连接,以及3种 HTTP请求,请求的URL分别对应着/url1、/url2、/url3

一个问题

假设mytest模块必须取出test_str配置 项的参数,可是在以上的例子中test_str出现了6个不同的参数值,分别为main、server80、 server8080、loc1、loc2、loc3,那么在mytest模块中我们取到的test_str值以哪一个为准呢?

关于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;
ngx_uint_t offset;
void post;
};

使用http配置项

1 创建数据结构用于存储配置项对应的参数

结构解析

typedef struct {
ngx_str_t my_str;
ngx_int_t my_num;
ngx_flag_t my_flag;
size_t my_size;
ngx_array_t* my_str_array;
ngx_array_t* my_keyval;
off_t my_off;
ngx_msec_t my_msec;
time_t my_sec;
ngx_bufs_t my_bufs;
ngx_uint_t my_enum_seq;
ngx_uint_t my_bitmask;
ngx_uint_t my_access;
ngx_path_t* my_path;
} ngx_http_mytest_conf_t;

成员解析:参照:一文读懂14种预设方法解析配置项_编程界的谢菲尔德的博客-CSDN博客

第二个问题:

为什么要这么严格地用一个结构体来存储配置项的参数值,而不是随意地定义几个全局 变量来存储它们呢?

初始化ngx_http_mytest_conf_t利用ngx_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;

解析:create_main_conf、create_srv_conf、create_loc_conf这3个回调方法负责把我们分 配的用于保存配置项的结构体传递给HTTP框架

问题三

为什么不是定义1个而是定义 3个回调方法

方法

普通的HTTP模块往往只实现create_loc_conf回调方法,因为它们只关注匹配某种URL的 请求。我们的mytest例子也是这样实现的,这里实现create_loc_conf的是 ngx_http_mytest_create_loc_conf方法

static void* ngx_http_conf_get_module_loc_conf(ngx_con_t cf)
{
    ngx_http_mytest_con_f mycf;
    mycf=(ngx_http_mytest_con_f*)ngx_pcalloccf->pool, sizeof(ngx_http_mytest_conf_t));
    if(mycf==NULL)
    {
        return NULL;
    }
     mycf->my_flag = NGX_CONF_UNSET;
mycf->my_num = NGX_CONF_UNSET;
mycf->my_str_array = NGX_CONF_UNSET_PTR;
mycf->my_keyval = NULL;
mycf->my_off = NGX_CONF_UNSET;
mycf->my_msec = NGX_CONF_UNSET_MSEC;
mycf->my_sec = NGX_CONF_UNSET;
mycf->my_size = NGX_CONF_UNSET_SIZE;
return mycf;
    
}

问题解析

问题一:

事实上,Nginx的设计是非常灵活的,它在每一个http块、server块或location块下,都会生成独立的数据结构来存放配置项。 因此,我们允许当用户访问的请求不同时(如请求的URL分别是/url1、/url2、/url3),配置 项test_str可以具有不同的值。那么,当请求是/url1时,test_str的值应当是location块下的 loc1,还是这个location所属的server块下的server80,又或者是其所属http块下的值main呢? 完全由mytest模块自己决定,我们可以定义这个行为

参照一:如何自定义配置项处理办法和合并_编程界的谢菲尔德的博客-CSDN博客

问题二:

多个location块(或者http块、 server块)中的相同配置项是允许同时生效的,也就是说,我们刚刚定义的 ngx_http_mytest_conf_t结构必须在Nginx的内存中保存许多份。事实上,HTTP框架在解析 nginx.conf文件时只要遇到http{}、server{}或者location{}配置块就会立刻分配一个新的 ngx_http_mytest_conf_t结构体。因此,HTTP模块感兴趣的配置项需要统一地使用一个struct结 构体来保存(否则HTTP框架无法管理),如果nginx.conf文件中在http{}下有多个server{}或 者location{},那么这个struct结构体在Nginx进程中就会存在多份实例。

问题三:

HTTP框架定义了3个级别的配置main、srv、loc,分别表示直接出现在http{}、 server{}、location{}块内的配置项。当nginx.conf中出现http{}时,HTTP框架会接管配置文件 中http{}块内的配置项解析当遇到http{...}配置 块时,HTTP框架会调用所有HTTP模块可能实现的create_main_conf、create_srv_conf、 create_loc_conf方法生成存储main级别配置参数的结构体;在遇到server{...}块时会再次调用 所有HTTP模块的create_srv_conf;在遇到location{...}时则会再次调create_loc_conf回调方法生成存储loc级别配置参数的 结构体。因此,实现这3个回调方法的意义是不同的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值