博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
nginx的location优化
阅读量:5756 次
发布时间:2019-06-18

本文共 4776 字,大约阅读时间需要 15 分钟。

微信公众号:

关注可了解更多的Nginx知识。任何问题或建议,请公众号留言;
关注公众号,有趣有内涵的文章第一时间送达!

简介

本篇文章主要是分析配置文件解析完毕之后对location的进一步优化。这一部分主要完成了静态树的构建,一切的目的就是为了更快捷的找到对应的location,提高http响应的速度。

代码分析

ngx_http_block()中有下面的一部分代码,如下:

1 /* create location trees */  2    for (s = 0; s < cmcf->servers.nelts; s++) {
3      // 当前server的ctx的loc_conf[ngx_http_core_module.ctx_index] 4        clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index]; 5 6        if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) {
7            return NGX_CONF_ERROR; 8        } 9 10        if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
11            return NGX_CONF_ERROR; 12        } 13    } 复制代码

上面的cmcfngx_http_core_modulehttp级别的ctxmain_conf数组中对应的配置结构体,类型为ngx_http_core_main_conf_t类型。经过前面分析,我们知道它的servers字段是一个动态数组,保存了当前配置文件中的所有server指令块对应的配置结构体。上面的代码就是遍历这个server数组,然后对每个server下面的location进行处理。下面我们看一下处理的过程:

ngx_http_init_locations

代码如下:

1static ngx_int_t   2ngx_http_init_locations(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,   3    ngx_http_core_loc_conf_t *pclcf)   4{
5    ngx_uint_t                   n; 6    ngx_queue_t                 *q, *locations, *named, tail; 7    ngx_http_core_loc_conf_t    *clcf; 8    ngx_http_location_queue_t   *lq; 9    ngx_http_core_loc_conf_t   **clcfp; 10#if (NGX_PCRE) 11    ngx_uint_t                   r; 12    ngx_queue_t                 *regex; 13#endif 14 15    locations = pclcf->locations; 16 17    if (locations == NULL) {
18        return NGX_OK; 19    } 20 21    ngx_queue_sort(locations, ngx_http_cmp_locations); 22 23    named = NULL; 24    n = 0; 25#if (NGX_PCRE) 26    regex = NULL; 27    r = 0; 28#endif 29 30    for (q = ngx_queue_head(locations); 31         q != ngx_queue_sentinel(locations); 32         q = ngx_queue_next(q)) 33    {
34        lq = (ngx_http_location_queue_t *) q; 35 36        clcf = lq->exact ? lq->exact : lq->inclusive; 37 38        if (ngx_http_init_locations(cf, NULL, clcf) != NGX_OK) {
39            return NGX_ERROR; 40        } 41 42#if (NGX_PCRE) 43 44        if (clcf->regex) {
45            r++; 46 47            if (regex == NULL) {
48                regex = q; 49            } 50 51            continue; 52        } 53 54#endif 55 56        if (clcf->named) {
57            n++; 58 59            if (named == NULL) {
60                named = q; 61            } 62 63            continue; 64        } 65 66        if (clcf->noname) {
67            break; 68        } 69    } 70 71    if (q != ngx_queue_sentinel(locations)) {
72        ngx_queue_split(locations, q, &tail); 73    } 74 75    if (named) {
76        clcfp = ngx_palloc(cf->pool, 77                           (n + 1) * sizeof(ngx_http_core_loc_conf_t *)); 78        if (clcfp == NULL) {
79            return NGX_ERROR; 80        } 81 82        cscf->named_locations = clcfp; 83 84        for (q = named; 85             q != ngx_queue_sentinel(locations); 86             q = ngx_queue_next(q)) 87        {
88            lq = (ngx_http_location_queue_t *) q; 89 90            *(clcfp++) = lq->exact; 91        } 92 93        *clcfp = NULL; 94 95        ngx_queue_split(locations, named, &tail); 96    } 97 98#if (NGX_PCRE) 99 100    if (regex) {
101 102        clcfp = ngx_palloc(cf->pool, 103                           (r + 1) * sizeof(ngx_http_core_loc_conf_t *)); 104        if (clcfp == NULL) {
105            return NGX_ERROR; 106        } 107 108        pclcf->regex_locations = clcfp; 109 110        for (q = regex; 111             q != ngx_queue_sentinel(locations); 112             q = ngx_queue_next(q)) 113        {
114            lq = (ngx_http_location_queue_t *) q; 115 116            *(clcfp++) = lq->exact; 117        } 118 119        *clcfp = NULL; 120 121        ngx_queue_split(locations, regex, &tail); 122    } 123 124#endif 125 126    return NGX_OK; 127} 复制代码

上面的代码首先调用ngx_queue_sort()函数对所有的location进行排序,排序之后的结果他如下:

  • 两个比较location中的未命名location(即noname为1,rewrite_module中if指令产生的location)排到后面;
  • 如果比较的两个location都为未命名location,则维持原次序:用户在配置文件里书写的先后顺序;
  • 两个比较location中的命名location(即named为1,@前缀)排到后面;
  • 如果比较的两个location都为命名location,则按字符串大小排序,名称字符序大的排到后面;
  • 两个比较location中的正则匹配location(即regex字段不为空)排到后面;
  • 如果比较的两个location都为正则匹配location,则维持原次序:用户在配置文件里书写的先后顺序;
  • 其他情况,按字符串大小排序。但对于两个location名称相同的情况,如果存在绝对匹配location,则把它放在前

紧接着将所有属于正则表达式和named的location分别放置到不同的地方,对于我们的例子,如下:

ngx_http_init_location之后的结构图

ngx_http_init_static_location_trees

这个函数主要是为了构建静态的location三叉树,由于我们的config文件中的location数量太少,这里没有办法进行仔细的讲解,所以具体的构建过程这里不详细的介绍,后面文章会仔细介绍这个过程,我们这里仅仅展示构建的最终结果:

最终形成的树结构

由于我们的配置文件只有一个location,所以形成的树结构只有一个节点,后面我们会分析多个location的时候如何构建这棵树。


喜欢本文的朋友们,欢迎长按下图关注订阅号郑尔多斯,更多精彩内容第一时间送达

郑尔多斯

转载地址:http://fynkx.baihongyu.com/

你可能感兴趣的文章
微信小程序之wx.navigateback往回携带参数
查看>>
陌陌和请吃饭之类的应用,你要是能玩转,那就厉害了
查看>>
递归的运行机制简单理解
查看>>
汉字转阿斯克马值
查看>>
Java 栈与堆简介
查看>>
【supervisord】部署单进程服务的利器
查看>>
zabbix oracle监控插件orabbix部署安装
查看>>
python3 通过qq 服务器 发送邮件
查看>>
java 多线程踩过的坑
查看>>
部署Replica Sets及查看相关配置
查看>>
倒序显示数组(从右往左)
查看>>
文献综述二:UML技术在行业资源平台系统建模中的应用
查看>>
阿里云服务器 linux下载 jdk
查看>>
Swift 学习 用 swift 调用 oc
查看>>
第三章 Python 的容器: 列表、元组、字典与集合
查看>>
微信小程序开发 -- 点击右上角实现转发功能
查看>>
与MS Project相关的两个项目
查看>>
[转载]ASP.NET MVC Music Store教程(1):概述和新项目
查看>>
使用 SharpSvn 执行 svn 操作的Demo
查看>>
js函数大全
查看>>