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 優先級官方文檔

  1. Directives with the = prefix that match the query exactly. If found, searching stops.
  2. All remaining directives with conventional strings, longest match first. If this match used the ^~ prefix, searching stops.
  3. Regular expressions, in order of definition in the configuration file.
  4. If #3 yielded a match, that result is used. Else the match from #2 is used.
  1. =前綴的指令嚴格匹配這個查詢。如果找到,停止搜索。
  2. 所有剩下的常規字符串,最長的匹配。如果這個匹配使用^〜前綴,搜索停止。
  3. 正則表達式,在配置文件中定義的順序。
  4. 如果第3條規則產生匹配的話,結果被使用。否則,如同從第2條規則被使用。

 

例如

location  = / {
  # 只匹配"/".
  [ configuration A ] 
}
location  / {
  # 匹配任何請求,因爲所有請求都是以"/"開始
  # 但是更長字符匹配或者正則表達式匹配會優先匹配
  [ configuration B ] 
}
location ^~ /images/ {
  # 匹配任何以 /images/ 開始的請求,並停止匹配 其它location
  [ configuration C ] 
}
location ~* \.(gif|jpg|jpeg)$ {
  # 匹配以 gif, jpg, or jpeg結尾的請求. 
  # 但是所有 /images/ 目錄的請求將由 [Configuration C]處理.   
  [ configuration D ] 
}

 

       可以看到上面的例子中有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

 

請求URI例子:

  • / -> 符合configuration A
  • /documents/document.html -> 符合configuration B
  • /images/1.gif -> 符合configuration C
  • /documents/1.jpg ->符合 configuration D

@location 例子
error_page 404 = @fetch;

location @fetch(
proxy_pass http://fetch;
)

 

location匹配命令

~      #波浪線表示執行一個正則匹配,區分大小寫
~*    #表示執行一個正則匹配,不區分大小寫
^~    #^~表示普通字符匹配,如果該選項匹配,只匹配該選項,不匹配別的選項,一般用來匹配目錄
=      #進行普通字符精確匹配
@     #"@" 定義一個命名的 location,使用在內部定向時,例如 error_page, try_files

 

 

location 匹配的優先級(與location在配置文件中的順序無關)
= 精確匹配會第一個被處理。如果發現精確匹配,nginx停止搜索其他匹配。
普通字符匹配,正則表達式規則和長的塊規則將被優先和查詢匹配,也就是說如果該項匹配還需去看有沒有正則表達式匹配和更長的匹配。
^~ 則只匹配該規則,nginx停止搜索其他匹配,否則nginx會繼續處理其他location指令。
最後匹配理帶有"~"和"~*"的指令,如果找到相應的匹配,則nginx停止搜索其他匹配;當沒有正則表達式或者沒有正則表達式被匹配的情況下,那麼匹配程度最高的逐字匹配指令會被使用。

 

參考:

http://www.nginx.cn/115.html

http://wiki.nginx.org/HttpCoreModule#location

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章