亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 網站 > Nginx > 正文

Nginx服務器中location配置的一些基本要點解析

2024-08-30 12:27:51
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了Nginx服務器中location配置的一些基本要點解析,特別對管理以及查找匹配作出了詳細的講解,需要的朋友可以參考下
 

在這一篇文章里,我將介紹nginx關于location的處理,大家都知道Nginx配置文件里面會有很多的location,nginx的配置指令的作用域可以分為 main,server,location這3個種,實際上這3者不是依次包含的關系,而是相互獨立的關系,比如一個只具有main級別作用域的指令,是不能寫在某個server或者location內的,模塊的某個指令可以同時具有main,server,location這3種作用域,另外每個模塊有 main,srv,loc這3個級別的配置,一個模塊的main級別的配置對所有的server和location都是共享的,srv級別的配置對所有 location都是共享的,location只有自己獨立的loc級別的配置,這就是為什么一個模塊的srv和loc級別的配置需要merge,而 main級別的配置不需要merge的原因。這里看起來有點繞,區分一下main,server,location分別作為一種作用域級別和一個主體,類似于形容詞和名字的區別,nginx的配置關系還是不難理解的。

        一般來說一個請求url過來,nginx會將它解析到某一個location來處理。這個解析的過程實際上根據location的配置基本可以分為字符串匹配和正則表達式匹配這2種。對于location的組織方式,最簡單的就是直接將它們保存為一個鏈表,解析url的時候一個一個遍歷即可找到相應location,但是這樣效率太低,對像nginx這種高性能的服務器來說是完全不可取的,nginx將字符串匹配的location組織成了一個三叉的字符串排序樹,而且建立的時候也考慮了樹的平衡性。文章后面我講詳細介紹源碼的實現。

        首先我來大概的介紹一下location的種類和匹配規則,以nginx wiki(http://wiki.nginx.org/HttpCoreModule#location)的例子做說明:

location = / {  # matches the query / only.  [ configuration A ]  } location / {  # matches any query, since all queries begin with /, but regular  # expressions and any longer conventional blocks will be  # matched first.  [ configuration B ]  } location ^~ /images/ {  # matches any query beginning with /images/ 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 the /images/ directory will be handled by  # Configuration C.    [ configuration D ]  }  location @named {  # Such locations are not used during normal processing of requests,   # they are intended only to process internally redirected requests (for example error_page, try_files).  [ configuration E ]  } 

        可以看到上面的例子中有5種不同類型的location,其中第4個帶 “~” 號前綴的為需要正則匹配的location,nginx在進行url解析時對這5種不同類型的location具有不同的優先級規則,大致的規則如下:

1,字符串精確匹配到一個帶 “=” 號前綴的location,則停止,且使用這個location的配置;

2,字符串匹配剩下的非正則和非特殊location,如果匹配到某個帶 "^~" 前綴的location,則停止;

3,正則匹配,匹配順序為location在配置文件中出現的順序。如果匹配到某個正則location,則停止,并使用這個location的配置;否則,使用步驟2中得到的具有最大字符串匹配的location配置。

       例如,對下面的請求有:

1, /   ->   精確匹配到第1個location,匹配停止,使用configuration A
2,/some/other/url    ->  首先前綴部分字符串匹配到了第2個location,然后進行正則匹配,顯然沒有匹配上,則使用第2個location的配置configurationB
3,/images /1.jpg  ->  首先前綴部分字符串匹配到了第2個location,但是接著對第3個location也前綴匹配上了,而且這時已經是配置文件里面對這個url的最大字符串匹配了,并且location帶有 "^~" 前綴,則不再進行正則匹配,最終使用configuration C
4,/some/other/path/to/1.jpg  -> 首先前綴部分同樣字符串匹配到了第2個location,然后進行正則匹配,這時正則匹配成功,則使用congifuration D

      nginx的url匹配規則實際上有點不妥,大部分情況下一個url必須先進行字符串匹配,然后再做正則匹配,但是實際上如果先做正則匹配,沒有匹配上再 做字符串匹配,在很多情況下可以節省掉做字符串匹配的時間。不管怎樣,先來看一下nginx源碼里面的實現,在介紹匹配location過程之前,先來介 紹一下nginx里面對location的組織方式,實際上在配置解析階段,nginx將字符串匹配的location和正則匹配的location分別 存儲在http core模塊的loc配置ngx_http_core_loc_conf_t結構的下面2個字段:

ngx_http_location_tree_node_t  *static_locations; (NGX_PCRE) ngx_http_core_loc_conf_t    **regex_locations; if 

從這2個字段的類型可以看出,字符串匹配的location被組織成了一個location tree,而正則匹配的location只是一個數組,

location tree和regex_locations數組建立過程在ngx_http_block中:/* create location trees */    for (s = 0; s < cmcf->servers.nelts; s++) {      clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];      if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) {       return NGX_CONF_ERROR;     }      if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {       return NGX_CONF_ERROR;     }   } 

        經過配置的讀取之后,所有server都被保存在http core模塊的main配置中的servers數組中,而每個server里面的location都被按配置中出現的順序保存在http core模塊的loc配置的locations隊列中,上面的代碼中先對每個server的location進行排序和分類處理,這一步發生在 ngx_http_init_location()函數中:

static ngx_int_t ngx_http_init_locations(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,   ngx_http_core_loc_conf_t *pclcf) {  ...   locations = pclcf->locations;   ...   /* 按照類型排序location,排序完后的隊列: (exact_match 或 inclusive) (排序好的,如果某個exact_match名字和inclusive location相同,exact_match排在前面)     | regex(未排序)| named(排序好的) | noname(未排序)*/   ngx_queue_sort(locations, ngx_http_cmp_locations);    named = NULL;   n = 0; #if (NGX_PCRE)   regex = NULL;   r = 0; #endif    for (q = ngx_queue_head(locations);      q != ngx_queue_sentinel(locations);      q = ngx_queue_next(q))   {     lq = (ngx_http_location_queue_t *) q;      clcf = lq->exact ? lq->exact : lq->inclusive;     /* 由于可能存在nested location,也就是location里面嵌套的location,這里需要遞歸的處理一下當前location下面的nested location */     if (ngx_http_init_locations(cf, NULL, clcf) != NGX_OK) {       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;     }   }    if (q != ngx_queue_sentinel(locations)) {     ngx_queue_split(locations, q, &tail);   }   /* 如果有named location,將它們保存在所屬server的named_locations數組中 */   if (named) {     clcfp = ngx_palloc(cf->pool,               (n + 1) * sizeof(ngx_http_core_loc_conf_t **));     if (clcfp == NULL) {       return NGX_ERROR;     }      cscf->named_locations = clcfp;      for (q = named;        q != ngx_queue_sentinel(locations);        q = ngx_queue_next(q))     {       lq = (ngx_http_location_queue_t *) q;        *(clcfp++) = lq->exact;     }      *clcfp = NULL;      ngx_queue_split(locations, named, &tail);   }  #if (NGX_PCRE)   /* 如果有正則匹配location,將它們保存在所屬server的http core模塊的loc配置的regex_locations 數組中,     這里和named location保存位置不同的原因是由于named location只能存在server里面,而regex location可以作為nested location */   if (regex) {      clcfp = ngx_palloc(cf->pool,               (r + 1) * sizeof(ngx_http_core_loc_conf_t **));     if (clcfp == NULL) {       return NGX_ERROR;     }      pclcf->regex_locations = clcfp;      for (q = regex;        q != ngx_queue_sentinel(locations);        q = ngx_queue_next(q))     {       lq = (ngx_http_location_queue_t *) q;        *(clcfp++) = lq->exact;     }      *clcfp = NULL;      ngx_queue_split(locations, regex, &tail);   }  #endif    return NGX_OK; } 

          
       上面的步驟將正則匹配的location保存好了,location tree的建立在ngx_http_init_static_location_trees中進行:

static ngx_int_t ngx_http_init_static_location_trees(ngx_conf_t *cf,   ngx_http_core_loc_conf_t *pclcf) {   ngx_queue_t        *q, *locations;   ngx_http_core_loc_conf_t  *clcf;   ngx_http_location_queue_t *lq;    locations = pclcf->locations;    if (locations == NULL) {     return NGX_OK;   }    if (ngx_queue_empty(locations)) {     return NGX_OK;   }   /* 這里也是由于nested location,需要遞歸一下 */   for (q = ngx_queue_head(locations);      q != ngx_queue_sentinel(locations);      q = ngx_queue_next(q))   {     lq = (ngx_http_location_queue_t *) q;      clcf = lq->exact ? lq->exact : lq->inclusive;      if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {       return NGX_ERROR;     }   }   /* join隊列中名字相同的inclusive和exact類型location,也就是如果某個exact_match的location名字和普通字符串匹配的location名字相同的話,     就將它們合到一個節點中,分別保存在節點的exact和inclusive下,這一步的目的實際是去重,為后面的建立排序樹做準備 */   if (ngx_http_join_exact_locations(cf, locations) != NGX_OK) {     return NGX_ERROR;   }   /* 遞歸每個location節點,得到當前節點的名字為其前綴的location的列表,保存在當前節點的list字段下 */   ngx_http_create_locations_list(locations, ngx_queue_head(locations));    /* 遞歸建立location三叉排序樹 */   pclcf->static_locations = ngx_http_create_locations_tree(cf, locations, 0);   if (pclcf->static_locations == NULL) {     return NGX_ERROR;   }    return NGX_OK; } 

        經過ngx_http_init_location()函數處理之后,locations隊列已經是排好序的了,建立三叉樹的過程的主要工作都在ngx_http_create_locations_list()和ngx_http_create_locations_tree()中完成,這2個 函數都是遞歸函數,第1個函數遞歸locations隊列中的每個節點,得到以當前節點的名字為前綴的location,并保存在當前節點的list字段 下,例如,對下列location:

location /xyz {  }  location = /xyz {  } location /xyza {  }  location /xyzab {  } location /xyzb {  } location /abc {  } location /efg {  } location /efgaa {  } 

        排序的結果為/abc  /efg   /efgaa  =/xyz  /xyz  /xyza /xyzab /xyzb,去重后結果為 /abc  /efg   /efgaa   /xyz  /xyza /xyzab/xyzb,ngx_http_create_locations_list()執行后的結果為:

Nginx服務器中location配置的一些基本要點解析

 最后,來看下ngx_http_create_locations_tree函數:

static ngx_http_location_tree_node_t * ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,   size_t prefix) {   ...   /* 根節點為locations隊列的中間節點 */   q = ngx_queue_middle(locations);    lq = (ngx_http_location_queue_t *) q;   len = lq->name->len - prefix;      node = ngx_palloc(cf->pool,            offsetof(ngx_http_location_tree_node_t, name) + len);   if (node == NULL) {     return NULL;   }    node->left = NULL;   node->right = NULL;   node->tree = NULL;   node->exact = lq->exact;   node->inclusive = lq->inclusive;    node->auto_redirect = (u_char) ((lq->exact && lq->exact->auto_redirect)               || (lq->inclusive && lq->inclusive->auto_redirect));    node->len = (u_char) len;   ngx_memcpy(node->name, &lq->name->data[prefix], len);    /* 從中間節點開始斷開 */   ngx_queue_split(locations, q, &tail);    if (ngx_queue_empty(locations)) {     /*      * ngx_queue_split() insures that if left part is empty,      * then right one is empty too      */     goto inclusive;   }    /* 從locations左半部分得到左子樹 */   node->left = ngx_http_create_locations_tree(cf, locations, prefix);   if (node->left == NULL) {     return NULL;   }    ngx_queue_remove(q);    if (ngx_queue_empty(&tail)) {     goto inclusive;   }      /* 從locations右半部分得到右子樹 */   node->right = ngx_http_create_locations_tree(cf, &tail, prefix);   if (node->right == NULL) {     return NULL;   }  inclusive:    if (ngx_queue_empty(&lq->list)) {     return node;   }    /* 從list隊列得到tree子樹 */   node->tree = ngx_http_create_locations_tree(cf, &lq->list, prefix + len);   if (node->tree == NULL) {     return NULL;   }    return node; }      location tree節點的ngx_http_location_tree_node_s結構:struct ngx_http_location_tree_node_s {   ngx_http_location_tree_node_t  *left;   ngx_http_location_tree_node_t  *right;   ngx_http_location_tree_node_t  *tree;    ngx_http_core_loc_conf_t    *exact;   ngx_http_core_loc_conf_t    *inclusive;    u_char              auto_redirect;   u_char              len;   u_char              name[1]; }; 

         location tree結構用到的是left,right,tree 這3個字段, location tree實際上是一個三叉的字符串排序樹,而且這里如果某個節點只考慮左,右子樹,它是一顆平衡樹,它的建立過程有點類似于一顆平衡排序二叉樹的建立過程,先排序再用二分查找找到的節點順序插入,ngx_http_location_tree_node_s的tree節點也是一顆平衡排序樹,它是用該節點由ngx_http_create_locations_list()得到的list建立的,也就是該節點的名字是它的tree子樹里面的所有節點名字的前綴,所以tree子樹里面的所有節點的名字不用保存公共前綴,而且查找的時候,如果是轉向tree節點的話,也是不需要再比較父節點的那段字符串了。
         ngx_http_create_locations_tree()函數寫的很清晰,它有一個參數是隊列locations,它返回一顆三叉樹,根節點為locations的中間節點,其左子樹為locations隊列的左半部分建立的location tree,右子樹為location隊列的右半部分建立的tree,tree節點為該根節點的list隊列建立的tree。

       最終建立的location tree如下(為了方便閱讀,圖中列出了tree節點的完整名字):

Nginx服務器中location配置的一些基本要點解析

 

PS:關于 location modifier
1. =
這會完全匹配指定的 pattern ,且這里的 pattern 被限制成簡單的字符串,也就是說這里不能使用正則表達式。

Example:server {  server_name vevb.com;  location = /abcd {  […]  }}

匹配情況:

  http://vevb.com/abcd    # 正好完全匹配  http://vevb.com/ABCD    # 如果運行 Nginx server 的系統本身對大小寫不敏感,比如 Windows ,那么也匹配  http://vevb.com/abcd?param1¶m2  # 忽略查詢串參數(query string arguments),這里就是 /abcd 后面的 ?param1¶m2  http://vevb.com/abcd/  # 不匹配,因為末尾存在反斜杠(trailing slash),Nginx 不認為這種情況是完全匹配  http://vevb.com/abcde  # 不匹配,因為不是完全匹配

2. (None)
可以不寫 location modifier ,Nginx 仍然能去匹配 pattern 。這種情況下,匹配那些以指定的 patern 開頭的 URI,注意這里的 URI 只能是普通字符串,不能使用正則表達式。

Example:server {  server_name vevb.com;  location /abcd {  […]  }}

匹配情況:

  http://vevb.com/abcd    # 正好完全匹配  http://vevb.com/ABCD    # 如果運行 Nginx server 的系統本身對大小寫不敏感,比如 Windows ,那么也匹配  http://vevb.com/abcd?param1¶m2  # 忽略查詢串參數(query string arguments),這里就是 /abcd 后面的 ?param1¶m2  http://vevb.com/abcd/  # 末尾存在反斜杠(trailing slash)也屬于匹配范圍內  http://vevb.com/abcde  # 仍然匹配,因為 URI 是以 pattern 開頭的

3. ~
這個 location modifier 對大小寫敏感,且 pattern 須是正則表達式

Example:server {  server_name vevb.com;  location ~ ^/abcd$ {  […]  }}

匹配情況:

  http://vevb.com/abcd    # 完全匹配  http://vevb.com/ABCD    # 不匹配,~ 對大小寫是敏感的  http://vevb.com/abcd?param1¶m2  # 忽略查詢串參數(query string arguments),這里就是 /abcd 后面的 ?param1¶m2  http://vevb.com/abcd/  # 不匹配,因為末尾存在反斜杠(trailing slash),并不匹配正則表達式 ^/abcd$  http://vevb.com/abcde  # 不匹配正則表達式 ^/abcd$

注意:對于一些對大小寫不敏感的系統,比如 Windows ,~ 和 ~* 都是不起作用的,這主要是操作系統的原因。

4. ~*
與 ~ 類似,但這個 location modifier 不區分大小寫,pattern 須是正則表達式

Example:server {  server_name vevb.com;  location ~* ^/abcd$ {  […]  }}

匹配情況:
  

 http://vevb.com/abcd    # 完全匹配  http://vevb.com/ABCD    # 匹配,這就是它不區分大小寫的特性  http://vevb.com/abcd?param1¶m2  # 忽略查詢串參數(query string arguments),這里就是 /abcd 后面的 ?param1¶m2  http://vevb.com/abcd/  # 不匹配,因為末尾存在反斜杠(trailing slash),并不匹配正則表達式 ^/abcd$  http://vevb.com/abcde  # 不匹配正則表達式 ^/abcd$

5. ^~
匹配情況類似 2. (None) 的情況,以指定匹配模式開頭的 URI 被匹配,不同的是,一旦匹配成功,那么 Nginx 就停止去尋找其他的 Location 塊進行匹配了(與 Location 匹配順序有關)

6. @
用于定義一個 Location 塊,且該塊不能被外部 Client 所訪問,只能被 Nginx 內部配置指令所訪問,比如 try_files or error_page



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产69精品久久久久9999| 2018中文字幕一区二区三区| 国产精品视频久久| 日韩欧美精品免费在线| 国产精品日韩一区| 久久人人爽人人| 欧美精品做受xxx性少妇| 久久精品国产久精国产思思| 精品香蕉在线观看视频一| 欧美激情综合色| 欧美日韩国产丝袜另类| 亚洲国产又黄又爽女人高潮的| 国产成人综合av| 亚洲一区二区三区sesese| 亚洲精品自拍偷拍| www.日韩视频| 久久男人资源视频| 97久久国产精品| 91精品国产成人www| 欧美日韩激情视频8区| 亚洲国产美女精品久久久久∴| 国产午夜精品免费一区二区三区| 欧美日韩视频在线| 亚洲人成网站在线播| 欧美电影免费观看网站| 成人在线精品视频| 久久免费视频观看| 在线电影中文日韩| 亚洲aa中文字幕| 亚洲精品国产免费| 亚洲最大的av网站| 国产精品自在线| 97热在线精品视频在线观看| 在线日韩中文字幕| 国产精品国产三级国产专播精品人| 国产精品jizz在线观看麻豆| 国产精品视频免费在线观看| 欧美日韩福利视频| 国产亚洲aⅴaaaaaa毛片| 亚洲一区二区中文| 国产精品久久久久久久电影| 亚洲欧美色婷婷| 亚洲精品狠狠操| 久久精品一本久久99精品| 日韩在线观看免费网站| 国产成人精品久久久| 日本午夜精品理论片a级appf发布| 精品国产福利视频| 亚洲国产精品电影| 国产精品成久久久久三级| 在线中文字幕日韩| 久久久精品免费视频| 久久亚洲一区二区三区四区五区高| 久久久久久久久亚洲| 亚洲性无码av在线| 久久精品美女视频网站| 亚洲va久久久噜噜噜| 国产99久久精品一区二区 夜夜躁日日躁| 中文字幕亚洲一区二区三区五十路| 久久精品国产清自在天天线| 国产精品福利在线| www.久久久久久.com| 91网站免费观看| 北条麻妃一区二区在线观看| 色综合视频网站| 精品久久久久久久久国产字幕| 久久久久久久久久久久久久久久久久av| 亚洲自拍欧美另类| 亚洲欧美一区二区三区久久| 欧美性色视频在线| 欧洲精品毛片网站| 97高清免费视频| 伊人久久免费视频| 久久手机精品视频| 久久久久久国产精品三级玉女聊斋| 中文字幕亚洲第一| 精品无人区乱码1区2区3区在线| 日韩av在线天堂网| 热草久综合在线| 国产免费一区视频观看免费| 国产亚洲精品激情久久| 国产v综合ⅴ日韩v欧美大片| 中文字幕日韩在线观看| 中国日韩欧美久久久久久久久| 日韩av一区在线| 亚洲高清一二三区| 国产精品第一第二| 久久99久久久久久久噜噜| 欧美日韩国产成人在线观看| 久久福利视频导航| 丰满岳妇乱一区二区三区| 日韩电影视频免费| 伊人亚洲福利一区二区三区| 日韩美女福利视频| 国产精品伦子伦免费视频| 亚洲精品欧美一区二区三区| 国产精品永久免费观看| 国产91精品在线播放| 久久久精品国产亚洲| 久热精品视频在线免费观看| 日韩视频精品在线| 久久久久亚洲精品| 欧美午夜久久久| 两个人的视频www国产精品| 欧美大片免费看| 91在线视频精品| 欧美性理论片在线观看片免费| 国产精品一区二区女厕厕| 正在播放亚洲1区| 亚洲天天在线日亚洲洲精| 欧美裸体xxxx极品少妇软件| 国产精品日韩av| 国产精品黄色av| 一本一本久久a久久精品综合小说| 亚洲精品久久视频| 欧美肥臀大乳一区二区免费视频| 午夜精品久久久久久99热软件| 亚洲free性xxxx护士白浆| 欧美资源在线观看| 韩国国内大量揄拍精品视频| 久久久精品一区二区| 久久精品99久久久香蕉| 另类少妇人与禽zozz0性伦| 精品调教chinesegay| 68精品久久久久久欧美| 国产成人鲁鲁免费视频a| 高清欧美一区二区三区| 亚洲欧美一区二区三区久久| 精品视频在线播放色网色视频| 国产精品福利在线观看网址| 日本不卡高字幕在线2019| 亚洲视频国产视频| 国产成人福利网站| 国内精品国产三级国产在线专| 欧美xxxwww| 亚洲小视频在线观看| 亚洲国产精彩中文乱码av在线播放| 国产成人精品优优av| xvideos国产精品| 韩国福利视频一区| 国产精品白丝jk喷水视频一区| 欧洲亚洲女同hd| 国产视频在线观看一区二区| 日韩在线观看免费高清| 欧美成人午夜激情视频| 国产亚洲综合久久| 中文字幕少妇一区二区三区| 欧美日韩国产精品| 国产精品日韩欧美综合| 亚洲白虎美女被爆操| 川上优av一区二区线观看| 欧美在线观看一区二区三区| 91精品久久久久久久久久久久久久| 美女少妇精品视频| 欧美限制级电影在线观看| 国产成人精品网站| 91国产视频在线| 98精品国产高清在线xxxx天堂| 亚洲美女精品成人在线视频| 欧美极品少妇xxxxⅹ免费视频| 日本精品视频在线播放| 亚洲精品中文字幕女同| 日韩影视在线观看| 成人国产精品免费视频|