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; } }