[nginx源码分析]location划分
2015-05-07 14:33
274 查看
整个ngx_http_block中的ngx_conf_parse配置解析完成,,后面主要对配置文件进行优化。
优化可以分为以下:
1 配置作用域合并
2 location划分
3 http header回调初始化hash
4 初始化http收包回调函数
5 server中的server_name形成hash
先对location类型概述:
从location语法中可以看到,基本可以分为4类locaiton
1 只包含一个url的是前缀匹配,即以这个指定字符为前缀的请求地址都能与它匹配上,比如请求地址”/document.html”, 以字符串”/”为前缀,所以能与配置B匹配上(当然,最终的匹配结果是否就是配置B,还需要看其他location配置,因为nginx采用的是最佳匹配)
2 如果加上=表示绝对匹配,则表示绝对匹配location,在上面的示例,只有当前处理请求的uri完全匹配字符串”/”(即不能多一个字符,也不能少一个字符)时,才被定位并使用对应的相关配置A
3 正则匹配location是由限定符” ~ ”(区分大小写)或“~*“(不区分大小写)指定的,此时给出的uri是一个正则表达式,请求地址满足该正则表达式的就能匹配上。
4 由限定符”^~”指定的location也是前缀匹配location,不过它暗示了在实际进行location定位时不用搜索正则匹配locaiton
5 还有另外两种地址分别称之为命名location和未命名locaiton,命名locaiton仅用于server内部跳转,看如下中rewrite就是命名location。
location@rewrite{
rewrite^/wiki/search(.*)$/search.php?search=$1 last;
}
其中在配置解析的时候(往前翻), 已经解析过location是保存在server上下文的loc_conf的locations 链表中。
下面的分析师对链表中的几点进行修剪。
函数是ngx_http_init_locations
首先是对server下的location进行排序,调用的函数是ngx_queue_sort,因为locations本身就是一个双向链表,然后该函数是典型的插入排序,比较函数是ngx_http_cmp_locations
ngx_queue_sort(locations,ngx_http_cmp_locations)
比较函数ngx_http_cmp_locations的算法原则是:
1 首先是如果比较的额两个节点中插入的是未命名的,那么把该节点加入到后面,如果比较的两个节点都是未命名的,那么保持原定次序。
2 如果插入的两个节点中,插入的是命名的location,那么把该节点加入到后面,如果比较的两个节点都是命名的,那么比较location名称,按照字母序进行排序。
3 如果两个比较节点中,插入的是正则location,那么就把插入即诶的那加入到后面,如果比较的两个节点都是正则,那么就按照原定次序,即保持用户在配置文件里书序的先后顺序。
所以插入的降序是未命名、命名、正则、前缀匹配|绝对匹配。
排序完后进行location切分。location排序完,整个list的结构是:
前缀匹配|绝对匹配--->正则匹配--->命名--> 未命名
切分就是遍历整个locationslist,然后找到正则匹配开始,命名匹配开始处
//这层循环主要是遍历整个locations链表找到regex的起始位置和named的起始位置
其他切分就不细说了,代码很easy,然后location就剩下前缀匹配和绝对匹配了。
然后对前缀匹配进行优化,函数是ngx_http_init_static_location_trees
优化可以分为以下:
1 配置作用域合并
2 location划分
3 http header回调初始化hash
4 初始化http收包回调函数
5 server中的server_name形成hash
先对location类型概述:
Syntax: location [ = | ~ | ~* | ^~ ] uri { ...} location = / { #matches the query /only [ configuration A ] } location / { #match any query ,since all queries begin with /, but regular #expression and any longer conventional blocks will be #match first [ configuration B ] } location ^~ /images/ { #matches any query beginning with /image/ and halts searching #so regular expressions will not be checked [ configuration C ] } location ~* \.(gif|jpg|jpeg)$ { # matches any request ending in gif,jpg, or jpeg .however, all # requests to be /images/ directory with be handled by config c [ configuration D ] }
从location语法中可以看到,基本可以分为4类locaiton
1 只包含一个url的是前缀匹配,即以这个指定字符为前缀的请求地址都能与它匹配上,比如请求地址”/document.html”, 以字符串”/”为前缀,所以能与配置B匹配上(当然,最终的匹配结果是否就是配置B,还需要看其他location配置,因为nginx采用的是最佳匹配)
2 如果加上=表示绝对匹配,则表示绝对匹配location,在上面的示例,只有当前处理请求的uri完全匹配字符串”/”(即不能多一个字符,也不能少一个字符)时,才被定位并使用对应的相关配置A
3 正则匹配location是由限定符” ~ ”(区分大小写)或“~*“(不区分大小写)指定的,此时给出的uri是一个正则表达式,请求地址满足该正则表达式的就能匹配上。
4 由限定符”^~”指定的location也是前缀匹配location,不过它暗示了在实际进行location定位时不用搜索正则匹配locaiton
5 还有另外两种地址分别称之为命名location和未命名locaiton,命名locaiton仅用于server内部跳转,看如下中rewrite就是命名location。
location@rewrite{
rewrite^/wiki/search(.*)$/search.php?search=$1 last;
}
其中在配置解析的时候(往前翻), 已经解析过location是保存在server上下文的loc_conf的locations 链表中。
下面的分析师对链表中的几点进行修剪。
函数是ngx_http_init_locations
首先是对server下的location进行排序,调用的函数是ngx_queue_sort,因为locations本身就是一个双向链表,然后该函数是典型的插入排序,比较函数是ngx_http_cmp_locations
ngx_queue_sort(locations,ngx_http_cmp_locations)
比较函数ngx_http_cmp_locations的算法原则是:
1 首先是如果比较的额两个节点中插入的是未命名的,那么把该节点加入到后面,如果比较的两个节点都是未命名的,那么保持原定次序。
2 如果插入的两个节点中,插入的是命名的location,那么把该节点加入到后面,如果比较的两个节点都是命名的,那么比较location名称,按照字母序进行排序。
3 如果两个比较节点中,插入的是正则location,那么就把插入即诶的那加入到后面,如果比较的两个节点都是正则,那么就按照原定次序,即保持用户在配置文件里书序的先后顺序。
所以插入的降序是未命名、命名、正则、前缀匹配|绝对匹配。
static ngx_int_t ngx_http_cmp_locations(const ngx_queue_t *one, const ngx_queue_t *two) { ngx_int_t rc; ngx_http_core_loc_conf_t *first, *second; ngx_http_location_queue_t *lq1, *lq2; lq1 = (ngx_http_location_queue_t *) one; lq2 = (ngx_http_location_queue_t *) two; first = lq1->exact ? lq1->exact : lq1->inclusive; second = lq2->exact ? lq2->exact : lq2->inclusive; if (first->noname && !second->noname) { /* shift no named locations to the end */ return 1; } if (!first->noname && second->noname) { /* shift no named locations to the end */ return -1; } if (first->noname || second->noname) { /* do not sort no named locations */ return 0; } if (first->named && !second->named) { /* shift named locations to the end */ return 1; } if (!first->named && second->named) { /* shift named locations to the end */ return -1; } if (first->named && second->named) { return ngx_strcmp(first->name.data, second->name.data); } #if (NGX_PCRE) if (first->regex && !second->regex) { /* shift the regex matches to the end */ return 1; } if (!first->regex && second->regex) { /* shift the regex matches to the end */ return -1; } if (first->regex || second->regex) { /* do not sort the regex matches */ return 0; } #endif rc = ngx_strcmp(first->name.data, second->name.data); if (rc == 0 && !first->exact_match && second->exact_match) { /* an exact match must be before the same inclusive one */ return 1; } return rc; }
排序完后进行location切分。location排序完,整个list的结构是:
前缀匹配|绝对匹配--->正则匹配--->命名--> 未命名
切分就是遍历整个locationslist,然后找到正则匹配开始,命名匹配开始处
//这层循环主要是遍历整个locations链表找到regex的起始位置和named的起始位置
for (q = ngx_queue_head(locations); q != ngx_queue_sentinel(locations); //遍历每一个location q = ngx_queue_next(q)) { lq = (ngx_http_location_queue_t *) q; clcf = lq->exact ? lq->exact : lq->inclusive; if (ngx_http_init_locations(cf, NULL, clcf) != NGX_OK) { //这里是一个递归,如果存在location下面还有locations的话还会进行递归调用 return NGX_ERROR; } #if (NGX_PCRE) if (clcf->regex) { r++; if (regex == NULL) { regex = q; } continue; } #endif if (clcf->named) { n++; if (named == NULL) { named = q; } continue; } if (clcf->noname) { break; } }
其他切分就不细说了,代码很easy,然后location就剩下前缀匹配和绝对匹配了。
然后对前缀匹配进行优化,函数是ngx_http_init_static_location_trees
相关文章推荐
- [nginx源码分析]配置解析(location作用域)
- nginx源码分析--内存对齐处理
- nginx源码分析--module开发(3)
- 数据结构---nginx-1.7.12源码分析 (双向链表)
- nginx源码分析之网络初始化
- nginx 负载均衡与location应用分析
- Nginx源码分析-内存池
- nginx源码分析—全局变量ngx_cycle的初始化
- Nginx源码分析-内存池
- Nginx 源码分析-- ngx_array、ngx_list基本数据结构
- Nginx源码分析—架构设计思想
- nginx源码那些事之array结构分析
- nginx源码分析-链表
- Nginx源码分析---hash结构ngx_hash_t(v1.0.4)
- Nginx源码分析-connections数组
- nginx源码分析—全局变量ngx_cycle的初始化
- Nginx源码分析2-概览
- nginx源码分析--GDB调试
- nginx 源码分析之框架
- nginx源码分析——内存池