nginx脚本引擎与设计设计(三)


        这一部分我们将探讨一些较细节的东西,加上前面(一),(二)两篇文章对典型情景的分析,我相信应该会对大家理解nginx的脚本解析机制有很大的帮助的。

 

        这里我们关注ngx_http_core_main_conf_t(下面简写为cmcf)结构中的这两个成员,cmcf->variables_keys和cmcf->variables,其中variables_keys是个hash数组,变量hash值相同的放到一个数组中,而且是唯一的,重复时会报错。重要的是这个hash数组,即cmcf->variables_keys,保存了整个系统中所有预定义的,自定义,几乎所有的变量(一些特定前缀的变量除外,如“http_”等,在函数ngx_http_variables_init_vars中都列出来了)。

 

我们分条目来看:

1.  系统中所有可能用到变量都会放到cmcf->variables_keys中。

 

2.  配置中出现的变量(在处理请求时会用到的),会放到cmcf->variables中。总体上来看,除去一些有特定前缀的变量(这类变量后面会讲),cmcf->variables可以看做是ngx_http_variables_init_vars的子集。从这里的设计可以看出来,系统定义的变量在请求处理时,并不会全部用到,我们只需根据配置,拿到有用的就可以了,所以cmcf->variables_keys使用了temp_pool(实际的元素则使用cf->pool),当variables收集变量完成之后,variables_keys结构也就没什么用处了。

 

3.  cmcf->variables是一个数组,它的元素类型为ngx_http_variable_t。

struct ngx_http_variable_s {

   // 变量名字符串

    ngx_str_t                    name; 

// 使用变量中的值设置request的某个成员的值,所谓set

    ngx_http_set_variable_pt   set_handler;

// 根据request中成员(如uri,args等)的值来设置,r->variables中对应变量的内容。 

    ngx_http_get_variable_pt   get_handler;

// 需要具体处理的具体内容,因为这个结构是通用的,那么具体处理的信息就放到// data成员中

    uintptr_t                    data;

// 一些标识信息,区别不同处理,后面会详细讲

    ngx_uint_t                   flags;

// 该变量在cmcf->variables数组中的下标

    ngx_uint_t                   index;

};

4.  在init_request阶段,我们看到有这样的处理:

r->variables =ngx_pcalloc(r->pool, cmcf->variables.nelts * sizeof(ngx_http_variable_value_t));

这里的设计思想是这样的,cmcf->variables是每个变量的处理信息的封装,而r-> variables里面则是处理该变量得到的内容(即value),所以cmcf->variables跟r->variables是一一对应的,成员之间就是var对value的关系,这不过这里的var和value是封装了很多信息的结构,不是单纯的值或字符串。这里我们看下r->variables的成员。

typedef struct {

    unsigned    len:28;

    unsigned    valid:1;          // 表示该变量在数组中并且有效,可以使用

// 表示使用该变量时,需要重新通过get_handler来获取,因为该变量的实际内容// 可能已经改变了。

    unsigned    no_cacheable:1; 

// 特定位置上的变量不存在(实际上是没有设置),那么它就是“not found”!

    unsigned    not_found:1;

    unsigned    escape:1; // 这里不管它,跟我们的情景没有多大关系

    u_char     *data;

} ngx_variable_value_t;

 

我们看到这个结构中处理包含代表直接变量值的指针和大小(即data和len)外,剩下的都是一些标记位。

 

下面我们看几个宏:

#define NGX_HTTP_VAR_CHANGEABLE   1

#define NGX_HTTP_VAR_NOCACHEABLE  2

#define NGX_HTTP_VAR_INDEXED       4

#define NGX_HTTP_VAR_NOHASH        8

 

1.  NGX_HTTP_VAR_CHANGEABLE

使用这个宏的时候意味着,该变量可以重复配置,一般后配置的会覆盖前面的配置。如:

set $file $1

set $file $2

那么结果就是file的最终值就是$2所代表的。

2.  NGX_HTTP_VAR_NOCACHEABLE

这个宏所影响的正是ngx_variable_value_t结构中的no_cacheable,前面注释里面提到过,凡是有该标记的变量,都要通过get_handler来获取变量的值。如下面函数:

ngx_http_get_flushed_variable(ngx_http_request_t *r, ngx_uint_tindex)

{

   ngx_http_variable_value_t  *v;

   v = &r->variables[index];

// 找到变量,发现是有效的,但是由于属于NGX_HTTP_VAR_NOCACHEABLE,所以// 需要在cmcf->variables找到它的处理结构来重新获取新值。

   if (v->valid) {  // 变量有效,具备可以使用的潜质

       if (!v->no_cacheable) { //可以直接用,就返回了

            return v;

       }

       // 这是一个NGX_HTTP_VAR_NOCACHEABLE类型的变量,那么…

       v->valid = 0;

       v->not_found = 0;

   }

// 重新获取,这个函数就不看了,大家可以自己分析

   returnngx_http_get_indexed_variable(r, index);

}

 

这种变量往往是跟特定的请求紧密相关的,如host,uri,args之类的,处理时每次重新获取新值时必要的。

3.  NGX_HTTP_VAR_INDEXED和NGX_HTTP_VAR_NOHASH

这两个宏主要是在SSI相关处理中用到,而ssi的处理需要用到cmcf->variables_hash,这是hash表,可以高效的找到变量。NGX_HTTP_VAR_NOHASH类型的变量压根就不会被放到这个hash表中,而从hash表中找到的变量,是ngx_http_variable_t结构,如果我们从它flags发现NGX_HTTP_VAR_INDEXED标记,那么意味着我们可以直接到r->variables中去找,至于找到后可用与否,那要另作判断了!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值