首頁 > 軟體

Nginx設定 location模組實現路由(反向代理、重定向)功能

2022-04-14 10:04:54

前置文章:

Linux(CentOS7) 下 Nginx1.15.8 安裝步驟

Nginx 的組態檔 nginx.conf

我們存取一個網址,伺服器返回對應的資源。那麼一個網址是如何對應一個資源的呢?
用 Nginx 可以很好地幫我們實現路由功能,我們所有需要做的就是設定好 location 模組。

語法規則

 location [=|~|~*|^~] /uri/ {… }

符號含義
=精確匹配 
^~非正則匹配
~正則匹配(區分大小寫)
~*正則匹配(不區分大小寫)
!~正則不匹配(區分大小寫)
!~*正則不匹配(不區分大小寫)
 普通匹配(這裡沒有符號的時候)

匹配規則

1. 精準匹配命中時,停止location

2.一般匹配(普通和非正則)命中時,對比所有命中的一般匹配,選出最長的一條

3.如果最長的那一條為非正則匹配,直接匹配此條,停止location

4.如果最長的那一條為普通匹配,繼續嘗試正則location(以上至此都不存在程式碼順序)

5.按程式碼順序執行正則匹配,當第一條正則location命中時,停止location

範例:

想執行以下範例需先下載第三方模組echo-nginx-module:

#下載到/usr/local/src目錄

wget https://github.com/openresty/echo-nginx-module/archive/v0.61.tar.gz

tar -zxvf v0.61.tar.gz                                 

#在Nginx原始碼目錄nginx-1.15.8下設定,--add-module指向模組目錄即會安裝外掛到nginx中

./configure --add-module=/usr/local/src/echo-nginx-module-0.61/

make && make install

#驗證安裝

nginx -V

你還需要設定 C:WindowsSystem32driversetchosts 檔案,新增“虛擬機器器ip 域名”到最後:

192.168.100.14 test.loaction.com

server {
 
	listen       80;
	server_name  test.location.com;
 
	#精準匹配測試
	#第1,2條雖然匹配,但第三條是精準匹配,出第三條結果
	#測試路徑/equal/a/b/c
	location ~ /equal/* {
		echo '/equal/*';
	}
	location /equal/a/b {
		echo '/equal/a/b';
	}
	location = /equal/a/b/c {
		echo '/equal/a/b/c';
	}
 
	#普通匹配測試
	#第1,2條雖然匹配,第三條匹配更長,出第三條結果
	#測試路徑/match/a/b/c
	location /match/a {
		return 200  "/match/a";
	}
	location /match/a/b {
		return 200  "/match/a/b";	
	}
	location /match/a/b/c {
		 return 200  "/match/a/b/c";
	}
	location /match/a/b/c/d {
		return 200  "/match/a/b/c/d"; 
	}
 
	#正則匹配覆蓋普通匹配,不會覆蓋非正則匹配
	#存取/re/a.htm,會被後面的正則覆蓋
	#存取/re/a/b開頭的路徑,不會被後面的正則覆蓋
	location /re/a.htm {
		 echo 'match /re/a.htm';
	}
	location ^~ /re/a/b {
		echo 'math ^~/re/a/b*';		
	}
	location ~ /re/(.*).(htm|js|css)$ {
		echo "cover /re/$1.$2";
	}
 
	#正則匹配成功一條後,便不再走其它正則
	#測試路徑/rex/a/b/c.htm
	location ~ /rex/.*.(htm|js|css)$ {
		echo "match first";
	}
	location ~ /rex/a/(.*).(htm|js|css)$ {
		echo "match second";
	}
	location ~ /rex/a/b/(.*).(htm|js|css)$ {
		echo "match third";
	}
}

結果:

精準匹配最優先:

一般匹配選最長:

正則覆蓋普通匹:

不能覆蓋非正則

正則匹配選首位:

proxy_pass 代理轉發

在上面的範例中,我們通過修改本機hosts檔案,讓本機存取 test.loaction.com 相當於存取 192.168.100.14。我們現在假設有一個服務在 192.168.100.15 這臺機器上。我們能不能通過存取 test.loaction.com,存取到 192.168.100.15 上的資源呢?

這樣的想法其實是在模擬實際做專案的時候,我們可以只購買一個域名,然後存取多個雲伺服器。我們要做的就是讓域名對應的伺服器具有代理轉發的功能。這裡是伺服器作為代理,讓使用者端能通過存取代理伺服器來存取其它伺服器,所以是反向代理。

通過在 location 裡設定 proxy_pass 就能實現代理轉發功能,幫助我們將請求轉發到別的伺服器。

我們先看範例再看規則:

server {
        listen       80;
        server_name	test.location.com;
 
        本機ip地址:192.168.100.104
 
        #後端服務路徑:
        http://192.168.100.105:8080/user/query?id=1
        
        #規則一:
        #存取路徑:http://test.location.com/user/query?id=1
        location /user {
        #path1:/user path2:/query 
                          #ip:port 後面無 /
               proxy_pass http://192.168.0.105:8080;
        }
        
        規則二:
        #存取路徑 :http://test.location.com/A/user/query?id=1
        location /A/user {
        #path1:/A/user path2:/query 
                           #ip:port 後面有 /xxx
                proxy_pass http://192.168.0.105:8080/user;
        }
       
    }

解讀:

後端服務路徑都是 http://192.168.100.105:8080/user/query?id=1。用規則一,可以使存取路徑為 http://test.location.com/user/query?id=1;用規則二,可以使存取路徑為 http://test.location.com/A/user/query?id=1。

規則:

1. 存取路徑格式為 sever_name + path1 + path2 + ?param

2. location 後面的路徑就是 path1,對照存取路徑格式,path1 和 ?param 之間的為path2

3. 如果 proxy_pass 後面的值形如 http: // ip : port; 那麼實際存取的地址是 http: // ip : port + path1 + path2 + ?param

4. 如果 proxy_pass 後面的值形如 http: // ip : port / xxx; (末尾相比上面有 /xxx)

    那麼實際存取的地址是 http: // ip : port  + path2 + ?param

規則二的作用:

如果我們存取其它伺服器都使用規則一,那麼我們將無法直觀地從 URL 確定這個服務屬於那臺機器或者哪種服務。

而如果使用規則二,我們可以通過合理的設定明確地知道,我們存取的是服務A。

root 與 index

nginx.conf 裡的預設 location 如下:

location / {
            root   html;
            index  index.html;
        }

意思是資原始檔的根目錄在 nginx 程式所在資料夾下的 html 資料夾:

如果我們沒有寫 URI,預設的資源是 html 資料夾下的 index.html

但是你如果這樣設定:

location / {
            root   html;
            index  index.html;
        }
 
location /index.html {
                echo "index";
        }

最後存取 http://test.location.com/ 瀏覽器會輸出 index:

也就是說,雖然前面設定了 index ,但是如果它對應的地址有被 location 匹配到的話,會執行 location 匹配後的結果

但是,必須還是得有 index 對應的檔案

為了驗證上面這一點,我把 html 目錄下的 index.html 改成 index,再 reload 並存取:

root 與 alias

還是先看範例比較直觀:

server {
        listen       80;
        server_name	test.local.com;
 
    #檔案地址:/etc/nginx/html/static/a.html
 
	#存取路徑:http://test.local.com/static/a.html 	
	location /static {
        #path1:/static path2:/a.html
        root /etc/nginx/html/;
        #檔案地址:root + path1 + path2
        }
 
	#存取路徑:http://test.local.com/target/a.html 
	location /target {
        #path1:/target path2:/a.html
        alias /etc/nginx/html/static/;
        #檔案地址:alias + path2
        }	       
    }

解讀:

檔案地址一樣,存取路徑可以不同。

使用 root 宣告的是根目錄,經過 location 匹配後,直接去根目錄下找存取路徑中 sever_name 後面的檔案地址。

使用 alias 宣告的是別名目錄,經過 location 匹配後,去別名目錄下找存取路徑中 sever_name 後面除去 location 匹配的地址的剩餘地址。這就好像給 location 匹配的地址取了個別名一樣。

規則

1. 存取路徑格式為 sever_name + path1 + path2 

2.  location 後面的路徑就是 path1,對照存取路徑格式,path1 後面的就是 path2

3. 如果使用 root ,檔案地址為:

    root + path1 +path2

4. 如果使用 alias ,檔案地址為:

   alias + path2

location 執行過程

結合以上內容,就很容易理解 location 執行過程了,如下圖

rewrite 重定向

location 裡還可以設定 rewrite 實現重定向:

rewrite regex replacement [flag];

其中:

regex:正規表示式

replacement :替換值flag:後續處理標識,可以為 break/last/permanent/redirect

重點在於 flag :

1. flag=break

發生 nginx 內部重定向,path值被更新,rewrite層面的命令會中斷。原控制流程邏輯不變往下走

2. flag=last

發生nginx內部重定向,path值被更新,rewrite層面的命令會中斷。控制流程重新整理,重新進行整個location層的邏輯流程

3. flag= permanent/redirect

發生頁面重定向(301永久重定向/302臨時重定向),nginx流程結束,返回http響應到瀏覽器,頁面url更新

4.flag為空

發生nginx內部重定向,path值被更新,rewrite層面的命令繼續。最後一個rewrite完畢,重新整理控制流程,重新進行location重匹配

範例:

server {
 
	listen       80;
	server_name  test.location.com;
 
	location /a.html {
		echo 'I am a.html';
	}
	location /b.html {
		echo 'I am b.html';
	}
 
	#此路徑請求:http://test.location.com/aa.html
	location /aa.html {##內部重定向
		rewrite ^/  /a.html break;##不會執行下面的rewrite		
		rewrite ^/  /b.html break;	
		root   /etc/nginx/html/;
	}
	
 
	#此路徑請求:http://test.location.com/ab.html
	location /ab.html {##內部重定向
		rewrite ^/  /a.html last;##不會執行下面的rewrite,但重新location匹配
		rewrite ^/  /b.html last;
		rewrite ^/  /c.html;
		root   /etc/nginx/html/;		
	}
 
	#此路徑請求:http://test.location.com/ba
	location /ba {
		rewrite ^/  /b.html permanent;##301永久重定向
		root   /etc/nginx/html/;
	}
 
 
	#此路徑請求:http://test.location.com/bb
	location /bb {
		rewrite ^/  /b.html redirect;##302臨時重定向
		set $aa 12;
		root   /etc/nginx/html/;
	}
	
	#此路徑請求:http://test.location.com/cc.html
	location /cc.html {
                rewrite ^/  /c.html;##指令不停,繼續往下
                rewrite ^/  /b.html;
                rewrite ^/  /a.html;##最後一條,生效的是這條
                root   /etc/nginx/html/;
        }
 
}

結果:

存取 http://test.location.com/aa.html,直接尋找 root 目錄下的 a.html,我沒有寫這個 html,所以是 404

存取 http://test.location.com/ab.html,因為重新 location 匹配了,所以匹配到了上面的 /a.html,輸出了一句話

存取 http://test.location.com/ba,永久重定向,可以看到位址列的網址都變了,是外部重定向

存取 http://test.location.com/bb,臨時重定向

存取 http://test.location.com/cc.html,不是 404,也經過了重新 location 匹配

Nginx 處理請求的11個階段

Nginx 處理請求的全過程一共劃分為 11 個階段(如圖),按階段由上到下依次執行 (上一階段的所有指令執行完畢,才進入下一階段)

各階段的含義如下:

  • post_read: 接收到完整的 http 頭部後處理的階段,在uri重寫之前。一般跳過
  • server_rewrite: location匹配前,修改uri的階段,用於重定向,location塊外的重寫指令(多次執行)
  • find_config: uri 尋找匹配的location塊設定項(多次執行)
  • rewrite:找到location塊後再修改uri,location級別的uri重寫階段(多次執行)
  • post_rewrite:防死迴圈,跳轉到對應階段
  • preaccess: 許可權預處理
  • access:判斷是否允許這個請求進入
  • post_access: 向用戶傳送拒絕服務的錯誤碼,用來響應上一階段的拒絕
  • try_files: 存取靜態檔案資源
  • content : 內容生成階段,該階段產生響應,並行送到使用者端
  • log:記錄存取紀錄檔

到此這篇關於Nginx設定 location模組實現路由(反向代理、重定向)功能的文章就介紹到這了,更多相關Nginx location 路由反向代理和重定向內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com