Nginx的location配置規則總結 - 運維筆記

 

Nginx幾乎是當下絕大多數公司在用的web應用服務,熟悉Nginx的配置,對於咱們平常的運維工做是相當重要的,下面就Nginx的location配置進行梳理:php

1)location匹配的是nginx的哪一個變量?css

$request_uri

2)location的匹配種類有哪些?html

格式:location [ 空格 | = | ~ | ~* | !~ | !~* | @ ] /uri/ {}
解釋:
=   表示精確匹配,若是找到,當即中止搜索並當即處理此請求。
~   表示執行一個正則匹配,區分大小寫匹配
~*  表示執行一個正則匹配,不區分大小寫匹配
!~  區分大小寫不匹配
!~* 不區分大小寫不匹配
^~  即表示只匹配普通字符(空格)。使用前綴匹配,^表示「非」,即不查詢正則表達式。若是匹配成功,則再也不匹配其餘location。
@   指定一個命名的location,通常只用於內部重定向請求。例如 error_page, try_files
/   表示通用匹配,任何請求都會匹配到

------------------------------------------------------------------------
對應示例說明:
1)=
server {
  server_name wangshibo.com;
  location = /abcd {
  […]
  }
}
匹配狀況:
    http://wangshibo.com/abcd        # 正好徹底匹配
    http://wangshibo.com/ABCD        # 若是運行 Nginx server 的系統自己對大小寫不敏感,好比 Windows ,那麼也匹配
    http://wangshibo.com/abcd?param1?m2    # 忽略查詢串參數(query string arguments),這裏就是 /abcd 後面的 ?param1?m2
    http://wangshibo.com/abcd/    # 不匹配,由於末尾存在反斜槓(trailing slash),Nginx 不認爲這種狀況是徹底匹配
    http://wangshibo.com/abcde    # 不匹配,由於不是徹底匹配

2)(None)
能夠不寫 location modifier ,Nginx 仍然能去匹配 pattern 。這種狀況下,匹配那些以指定的 patern 開頭的 URI,注意這裏的 URI 只能是普通字符串,不能使用正則表達式。
server {
  server_name website.com;
  location /abcd {
  […]
  }
}
匹配狀況:
    http://wangshibo.com/abcd        # 正好徹底匹配
    http://wangshibo.com/ABCD        # 若是運行 Nginx server 的系統自己對大小寫不敏感,好比 Windows ,那麼也匹配
    http://wangshibo.com/abcd?param1?m2    # 忽略查詢串參數(query string arguments),這裏就是 /abcd 後面的 ?param1?m2
    http://wangshibo.com/abcd/    # 末尾存在反斜槓(trailing slash)也屬於匹配範圍內
    http://wangshibo.com/abcde    # 仍然匹配,由於 URI 是以 pattern 開頭的

3)~
這個 location modifier 對大小寫敏感,且 pattern 須是正則表達式
server {
  server_name wangshibo.com;
  location ~ ^/abcd$ {
  […]
  }
}
匹配狀況:
    http://wangshibo.com/abcd        # 徹底匹配
    http://wangshibo.com/ABCD        # 不匹配,~ 對大小寫是敏感的
    http://wangshibo.com/abcd?param1?m2    # 忽略查詢串參數(query string arguments),這裏就是 /abcd 後面的 ?param1?m2
    http://wangshibo.com/abcd/    # 不匹配,由於末尾存在反斜槓(trailing slash),並不匹配正則表達式 ^/abcd$
    http://wangshibo.com/abcde    # 不匹配正則表達式 ^/abcd$
注意:對於一些對大小寫不敏感的系統,好比 Windows ,~ 和 ~* 都是不起做用的,這主要是操做系統的緣由。

4)~*
與 ~ 相似,但這個 location modifier 不區分大小寫,pattern 須是正則表達式
server {
  server_name website.com;
  location ~* ^/abcd$ {
  […]
  }
}
匹配狀況:
    http://wangshibo.com/abcd        # 徹底匹配
    http://wangshibo.com/ABCD        # 匹配,這就是它不區分大小寫的特性
    http://wangshibo.com/abcd?param1?m2    # 忽略查詢串參數(query string arguments),這裏就是 /abcd 後面的 ?param1?m2
    http://wangshibo.com/abcd/    # 不匹配,由於末尾存在反斜槓(trailing slash),並不匹配正則表達式 ^/abcd$
    http://wangshibo.com/abcde    # 不匹配正則表達式 ^/abcd$

5)^~
匹配狀況相似 2. (None) 的狀況,以指定匹配模式開頭的 URI 被匹配,不一樣的是,一旦匹配成功,那麼 Nginx 就中止去尋找其餘的 Location 塊進行匹配了(與 Location 匹配順序有關)

6. @
用於定義一個 Location塊,且該塊不能被外部Client 所訪問,只能被Nginx內部配置指令所訪問,好比try_files 或 error_page
	location @resize {
            rewrite ^/(.*)/cache/(.*)?(.*)$ /resize.php?dir=$1&path=$2$3;
            rewrite ^/(.*)/orgi/cert/(.*)?(.*)$ /pass/resize?dir=$1&type=cert&path=$2$3&is_orgi=true;
            rewrite ^/(.*)/orgi/card/(.*)?(.*)$ /pass/resize?dir=$1&type=card&path=$2$3&is_orgi=true;
            rewrite ^/(.*)/orgi/(.*)/(.*)?(.*)$ /pass/resize?dir=$1&type=$2&path=$3$4&is_orgi=true;
            include fastcgi_params;
        }

以下示例:nginx

#通用匹配
location / {
	  root /var/www/web/;
	  autoindex on;
	  autoindex_exact_size off;
	  autoindex_localtime on;
	  access_log /var/www/log/nginx/access.log;
	  error_log /var/www/log/nginx/error.log;
}

#正則匹配
#proxy the php scripts to php-fpm
location ~ \.php(.*)$  {
        root /var/www/web/;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_read_timeout 300;
        }

#精確匹配
location = /hello.php {
		root /var/www/web/;
		rewrite ^(.*)$ http://www.wangshibo.com  redirect;
}


產生的效果以下:
訪問根目錄/,匹配到location /
訪問除hello.php以外的其它php程序,匹配到location ~ \.php$,而且用php5-fpm去運行
訪問hello.php,匹配到location = /hello.php,訪問被重定向到http://www.wangshibo.com

3)location搜索優先級順序如何?web

精確匹配 > 字符串匹配( 長 > 短 [ 注: ^~ 匹配則中止匹配 ]) > 正則匹配( 上 > 下 )
==========================================================================================================================
在nginx的location和配置中location的順序沒有太大關係。正location表達式的類型有關。
相同類型的表達式,字符串長的會優先匹配。
  
優先級排列(下面是在location匹配的內容是同樣長度的path內容的狀況下,好比匹配的path都是images的狀況下):
1)等號類型(=)的精確匹配優先級最高,精確匹配只能命中一個。一旦匹配成功,則再也不查找其餘匹配項。
2)^~類型表達式,即字符串匹配,使用匹配最長的最爲匹配結果。一旦匹配成功,則再也不查找其餘匹配項。
3)正則表達式類型(~ ~*)的優先級次之。若是有多個location的正則能匹配的話,則使用正則表達式最長的那個。
4)常規字符串匹配類型。按前綴匹配。
  
特別注意:
字符串匹配優先搜索,可是隻是記錄下最長的匹配 (若是 ^~ 是最長的匹配,則會直接命中,中止搜索正則),而後繼續搜索正則匹配,
若是有正則匹配,則命中正則匹配,若是沒有正則匹配,則命中最長的字符串匹配.
--------------------------------------------------------------------------------------
結論:
去分和不區分大小寫的正則匹配優先級相同,以前後順序來決定匹配哪個.
=的優先級比~高
=的優先級比 ^~高
^~的優先級比~高
^~優先匹配的是從根開始的匹配
不加的優先級比~低
~與*~正則匹配的優先級按前後次序來決定的

--------------------------------------------------------------------------------------
即nginx匹配的優先級順序爲:
[不加] <   [~/~*]   <    [^~]   <    [=]
--------------------------------------------------------------------------------------

下面經過示例進行驗證:
1)先來測試下區分大小寫和不區分大小寫的優先級.以下:
  
   location ~ /5b.txt {
          return 501;
   }
  
   location ~* /5b.txt {
          return 504;
   } 
  
測試結果爲:
http://192.168.1.80/5b.txt ------------501
http://192.168.1.80/5B.txt ------------504
  
將順序反下,將~*放前面
   location ~* /5b.txt {
          return 501;
   }
  
   location ~ /5b.txt {
          return 504;
   } 
  
測試結果爲:
http://192.168.1.80/5b.txt ------------501
http://192.168.1.80/5B.txt ------------501
  
結論: 去分和不區分大小寫的正則匹配優先級相同,以前後順序來決定匹配哪個.
  
2)再來比較=與~的優先級
  
   location = /5b.txt {
          return 502;
   }
  
   location ~ /5b.txt {
          return 504;
   } 
  
測試結果爲:
http://192.168.1.80/5b.txt -------------502
  
結論:=的優先級比~高
  
3)再來比較下 ^~ 與 ~的優先級
  
   location ~ /5b.txt {
          return 502;
   }
  
   location ^~ /5b.txt {
          return 504;
   } 
  
測試結果爲:
http://192.168.1.80/5b.txt  --------------504
  
結論:^~的優先級比~高
  
  
4)再測試 ^~ 與 = 的優先級
  
   location ^~ /5b.txt {
          return 502;
   }
  
   location = /5b.txt {
          return 504;
   } 
  
測試結果:
http://192.168.1.80/5b.txt  --------------504
  
結論:=的優先級比 ^~高
  
5)再來測試^~同級之間的優先級
  
   location ^~ 5b.txt {
          return 502;
   }
  
   location ^~ /5b.txt/ {
          return 504;
   }
  
  
測試結果:
http://192.168.1.80/5b.txt  --------------504
  
結論 :^~優先匹配的是從根開始的匹配
  
6)再來看空格(即什麼都不加)與~的優先級比較
  
   location /5b.txt {
          return 502;
   }
  
   location ~ /5b.txt {
          return 504;
   }
  
測試結果爲:
http://192.168.1.80/5b.txt  --------------504
  
結論:空格的優先級比~低
  
優先級排序爲:
空格(即不加)
~與*~正則匹配的優先級按前後次序來決定的
^~同級之間的匹配是按照根目錄順序來的
  
------------------------------------------------------------------------------------------
再來看看下面的例子 (這裏爲了方面測試內容輸出,使用了echo-nginx-module):
  
1)精確匹配,即「=」
location = /images/test.png {
    echo 'config1';
}
  
location  /images/test.png {
    echo 'config2';
}
  
location \/images\/test\.png$ {
    echo 'config3';
}
  
若是此時請求 http://127.0.0.1/images/test.png 輸出的內容是config1, 毋容置疑,精確匹配優先級最高!
  
2)精確匹配的特殊狀況
location = / {
    index index.html;
}
  
location / {
    echo 'config2';
}
  
此時輸入http://127.0.0.1 輸出的內容是config2, 怎麼精確匹配的優先級不靈了呢?
是這樣的,精確匹配仍是起做用了,請求目錄(非具體文件),nginx會將請求內部定向到index文件,
既此時真正的請求是http://127.0.0.1/index.html, 這是config2則被命中!
因此精確匹配不要用來匹配/
  
3)字符串搜索與正則搜索
location /images/test.png {
    echo 'config1';
}
  
location ^~ /images/ {
    echo 'config2';
}
  
location ~ \/images\/test\.png$ {
    echo 'config3';
}
  
location ~ \/images\/ {
    echo 'config4';
}
  
若是此時請求http://127.0.0.1/images/test.png 輸出的內容是config3,正則命中。
(雖然config1爲最長匹配的字符串,此時只作記錄,後面還要搜索正則匹配,則config3正則匹配命中),
仔細觀察能夠發現config4也被匹配成功了,可是正則的匹配順序是按照location的定義順序匹配的,因此config3命中(注意示例中帶了"\"的正則的轉義符).
  
4)字符串匹配優先級的提高( ^~ )
location /images/ {
    echo 'config1';
}
  
location ^~ /images/test.png {
    echo 'config2';
}
  
location ~ /images/test\.png$ {
    echo 'config3';
}
  
location ~ \/images\/ {
    echo 'config4';
}
  
若是此時請求 http://127.0.0.1/images/test.png 輸出的內容是config2, 首部匹配命中。
(由於字符串匹配是優先搜索的,此時發現config2 爲最長的字符串匹配且爲^~匹配方式,因此中止搜索正則,直接命中!)
  
因此這裏的 ^~ 符號比較特殊,就是爲了提升字符串匹配的優先級,優先於正則匹配.
------------------------------------------------------------------
/ 通用匹配,任何請求都會匹配到。
多個location配置的狀況下,須要遵循:
首先匹配=
其次匹配^~
再其次按照配置文件的順序進行正則匹配、
最後是交給/進行通用匹配
注意:當有匹配成功時,馬上中止匹配,按照當前匹配規則處理請求
 
看看下面匹配規則:
#規則A
location = / {
}
 
#規則B
location = /login {
}
 
#規則C
location ^~ /static/ {
}
 
#規則D
location ~ \.(gif|jpg|png|js|css)$ {
}
 
#規則E
location ~* \.png$ {
}
 
#規則F
location !~ \.xhtml$ {
}
 
#規則G
location !~* \.xhtml$ {
}
 
#規則H
location / {
}
 
那麼產生的效果以下:
1)訪問根目錄/, 好比http://localhost/ 將匹配規則A
2)訪問 http://localhost/login 將匹配規則B,http://localhost/register 則匹配規則H
3)訪問 http://localhost/static/a.html 將匹配規則C
4)訪問 http://localhost/a.gif, http://localhost/b.jpg 將匹配規則D和規則E,可是規則D順序優先,規則E不起做用,而 http://localhost/static/c.png 則優先匹配到規則C
5)訪問 http://localhost/a.PNG 則匹配規則E,而不會匹配規則D,由於規則E不區分大小寫。
6)訪問 http://localhost/a.xhtml 不會匹配規則F和規則G,http://localhost/a.XHTML不會匹配規則G,由於不區分大小寫。規則F,規則G屬於排除法,符合匹配規則可是不會匹配到,因此想一想看實際應用中哪裏會用到。
7)訪問 http://localhost/category/id/1111 則最終匹配到規則H,由於以上規則都不匹配,這個時候應該是nginx轉發請求給後端應用服務器,好比FastCGI(php),tomcat(jsp),nginx做爲方向代理服務器存在。
 
注意:在實際使用中,至少清楚下面匹配規則
1)直接匹配網站根,經過域名訪問網站首頁比較頻繁,使用這個會加速處理,官網如是說。
2)這裏是直接轉發給後端應用服務器了,也能夠是一個靜態首頁
 
第一個必選規則:
location = / {
    proxy_pass http://tomcat:8080/index
}
 
第二個必選規則是處理靜態文件請求,這是nginx做爲http服務器的強項
有兩種配置模式,目錄匹配或後綴匹配,任選其一或搭配使用
location ^~ /static/ {
    root /webroot/static/;
}
 
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
    root /webroot/res/;
}
 
第三個規則就是通用規則,用來轉發動態請求到後端應用服務器
非靜態文件請求就默認是動態請求,本身根據實際把握
畢竟目前的一些框架的流行,帶.php,.jsp後綴的狀況不多了
location / {
    proxy_pass http://tomcat:8080/
}

看看下面幾個設置正則表達式

# 重寫跳轉
rewrite  "^/conference/([^/]+)$" /con_detail.php?con_title=$1 last;
rewrite  "^/conference/([^/]+)/$" /con_detail.php?con_title=$1 last;

#屏蔽爬蟲
if ($http_user_agent ~* "qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo! Slurp|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot|ia_archiver|Tomato Bot")
    {
    return 403;
    }

#favicon.ico不用打日誌
   location = /favicon.ico {
      log_not_found off;
      access_log off;
    }

#不容許訪問隱藏文件
location ~ /\. {
    deny all;
    access_log off;
    log_not_found off;
}

#訪問圖片,flash文件等不用打日誌
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
    expires      7d; #文件返回的過時時間是7天
    access_log off;
}

#訪問js和css文件不用打日誌
location ~ .*\.(js|css)?$ {
    expires      1d; #文件返回的過時時間是1天
    access_log off;
}


#設置php-cgi
location ~ [^/]\.php(/|$) {
    fastcgi_split_path_info ^(.+?\.php)(/.*)$;
    #攔截不存在的php頁面請求
    if (!-f $document_root$fastcgi_script_name) {
        return 404;
    }

}
相關文章
相關標籤/搜索