[nginx源码分析]location划分
来源:互联网 发布:apt get 修改源码 编辑:程序博客网 时间:2024/04/29 03:38
整个ngx_http_block中的ngx_conf_parse配置解析完成,,后面主要对配置文件进行优化。
优化可以分为以下:
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源码分析]配置解析(location作用域)
- nginx 负载均衡与location应用分析
- nginx源码分析
- Nginx源码分析-数组
- nginx源码分析-链表
- Nginx源码分析链接
- 关于nginx源码分析
- nginx源码分析
- nginx源码分析-链表
- nginx源码分析
- Nginx源码分析
- Nginx源码分析链接
- Nginx源码分析一
- Nginx源码分析1
- Nginx源码分析-ngx_htttp_footer_filter_module
- Nginx 源码结构分析
- Nginx 源码结构分析
- eMMC介绍
- How to Create a Secure Login Script in PHP and mySQL
- 【Unity3d】学习笔记(11)——处理CSV文件
- 编辑器材质球的修改
- 第40课作业第二题
- [nginx源码分析]location划分
- Linux 下修改Tomcat使用的JVM内存大小
- LeetCode (31) Divide two integers (不使用 *, /, mod 求两个数相除结果)
- GitHub for Windows使用方法
- php执行exe文件需注意的问题
- 点击按钮生成Excel
- 利用mybatis-paginator实现分页
- ervlet/filter/listener/interceptor区别与联系
- php超时的处理方法