10.5 location的快速检索

从10.2.3节中可以了解到,每一个server块可以对应着多个location块,而一个location块还可以继续嵌套多个location块。每一批location块是通过双向链表与它的父配置块(要么属于server块,要么属于location块)关联起来的。由双向链表的查询效率可以知道,当一个请求根据10.4节中描述过的散列表快速查询到server块时,必须遍历其下的所有location组成的双向链表才能找到与其URI匹配的location配置块,这也是用户无法接受的。下面看看HTTP框架又是怎样通过静态的二叉查找树来保存location的。


//cmcf就是该http块下全局的ngx_http_core_main_conf_t结构体

cmcf=ctx->main_conf[ngx_http_core_module.ctx_index];

/cscfp指向保存所有ngx_http_core_srv_conf_t结构体指针的servers动态数组的第1个元素/

cscfp=cmcf->servers.elts;

//遍历http块下的所有server块

for(s=0;s<cmcf->servers.nelts;s++){

/clcf是server块下的ngx_http_core_loc_conf_t结构体,10.2.3节曾经介绍过它的locations成员以双向链表关联着隶属于这个server块的所有location块对应的ngx_http_core_loc_conf_t结构体/

clcf=cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];

/将ngx_http_core_loc_conf_t组成的双向链表按照location匹配字符串进行排序。注意:这个操作是递归进行的,如果某个location块下还具有其他location,那么它的locations链表也会被排序/

if(ngx_http_init_locations(cf,cscfp[s],clcf)!=NGX_OK){

return NGX_CONF_ERROR;

}

/根据已经按照location字符串排序过的双向链表,快速地构建静态的二叉查找树。与ngx_http_init_locations方法类似,这个操作也是递归进行的/

if(ngx_http_init_static_location_trees(cf,clcf)!=NGX_OK){

return NGX_CONF_ERROR;

}

}


注意,这里的二叉查找树并不是第7章中介绍过的红黑树,不过,为什么不使用红黑树呢?因为location是由nginx.conf中读取到的,它是静态不变的,不存在运行过程中在树中添加或者删除location的场景,而且红黑树的查询效率也没有重新构造的静态的完全平衡二叉树高。

这棵静态的二叉平衡查找树是用ngx_http_location_tree_node_t结构体来表示的,如下所示。


typedef struct ngx_http_location_tree_node_s ngx_http_location_tree_node_t;

struct ngx_http_location_tree_node_s{

//左子树

ngx_http_location_tree_node_t*left;

//右子树

ngx_http_location_tree_node_t*right;

//无法完全匹配的location组成的树

ngx_http_location_tree_node_t*tree;

/如果location对应的URI匹配字符串属于能够完全匹配的类型,则exact指向其对应的ngx_http_core_loc_conf_t结构体,否则为NULL空指针/

ngx_http_core_loc_conf_t*exact;

/如果location对应的URI匹配字符串属于无法完全匹配的类型,则inclusive指向其对应的ngx_http_core_loc_conf_t结构体,否则为NULL空指针/

ngx_http_core_loc_conf_t*inclusive;

//自动重定向标志

u_char auto_redirect;

//name字符串的实际长度

u_char len;

//name指向location对应的URI匹配表达式

u_char name[1];

};


HTTP框架在ngx_http_core_module模块中定义了ngx_http_core_find_location方法,用于从静态二叉查找树中快速检索到ngx_http_core_loc_conf_t结构体,这在第11章探讨HTTP请求的处理过程时将会碰到。