天天看點

第六章 Nginx伺服器的Rewrite功能

概述:Rewrite位址修改,重定向問題

本章涉及内容:

  • 後端伺服器組的配置指令
  • Rewrite功能的配置指令
  • Rewrite功能的多種應用

6.1、Nginx後端伺服器組的配置的5個指令

Nginx伺服器支援設定一組伺服器作為後端伺服器(設定伺服器)

它們是由标準HTTP子產品ngx_http_upstream_module進行解析

1、upstream指令

該指令時設定後端伺服器組的主要指令

upstream name { ... }

name 是給後端伺服器組起的組名

花括号中列出後端伺服器組中包含的伺服器。

預設值采用輪叫排程(Round-Robin RR)政策順序選擇  (輪詢直到響應正常)

2、server指令

可以設定權重和其他參數

該指令用于設定組内的伺服器。

server address [parameters]

address : 伺服器的位址 可以是包含端口号的IP位址(IP:Port)、域名或者以“unix:”為字首用于程序間通信的Unix Domain Socket

parameters. 這裡有很多屬性

weight=number  為組内伺服器設定權重,權重值高的伺服器被優先用于處理請求。權重輪叫政策。組内所有伺服器的權重預設設定為1

max_fails=number 設定一個請求失敗的次數 預設設定為1。如果設定為0,則不使用上面的辦法檢查伺服器是否有效。超過次數,伺服器認為無效。

HTTP 404 狀态不被認為是請求失敗

fail_timeout=time  預設設定為10s 設定max_fails指令嘗試請求某台組内伺服器的時間

backup  将某台組内伺服器标記為備用伺服器,隻有當正常伺服器出于無效狀态或繁忙狀态時,該伺服器才被用來處理用戶端請求。

down、将某台組内伺服器記為永久的無效狀态,通常與ip_hash指令配合使用。

upstream backend
{

  server backend1.example.com weight=5;
  server127.0.0.1:8080 max_fails=3 fail_timeout=30s;
  server unix:/tmp/backend3;
}
           

設定一個名為backend的伺服器組,組内包含三台伺服器,分别是基于域名的backend1.example.com、基于IP位址的127.0.0.1:8080和用于程序間通信的Unix Domain Socket。

backend1.example.com的權重設定為5,為組内最大,優先接收和處理請求;對本地伺服器127.0.0.1:8080的狀态檢查設定是,如果在30s内連續産生3次請求失敗,則該伺服器在之後的30s内被認為是無效(down)狀态

3、ip_hash指令

實作會話保持功能,将某個用戶端的多次請求定向到組内同一台伺服器上。保證用戶端與伺服器之間建立穩定的會話。

ip_hash;  (某個伺服器down,才會選擇下一個伺服器) ip_hash指令不能與server指令中的weight變量一起使用。ip_hash技術主要根據用戶端IP位址配置設定伺服器。

upstream backend
{
  ip_hash;
  server myback1.proxy.com;
  server myback2.proxy.com;

}
           

4、keepalive指令

該指令用于控制網絡連接配接保持功能。

keepalive connections;  

connections 為Nginx伺服器的每一個工作程序允許該伺服器組保持的空閑網絡連接配接數的上限值。如果超過該值,工作程序将采用最近最少使用的政策關閉網絡連接配接。

5、least_conn指令

該指令用于配置Nginx伺服器使用負載均衡政策為網絡連接配接配置設定伺服器組内的伺服器。

6.2、Rewrite功能的配置

URL的重寫。Rewrite功能依賴于PCRE(Perl Compatible Regular Expressions, Perl 相容的正規表達式)

6.2.1、“位址重寫”與“位址轉發”

位址重寫:為了實作位址标準化 google.cn 、google 、在伺服器中被改變為www.google.com

轉發: 指将一個域名指到另一個已有站點的過程。

位址重寫和位址轉發差別

  • 位址轉發後用戶端浏覽器位址中的位址顯示是不改變的,而位址重寫後用戶端浏覽位址欄中的位址改變為伺服器選擇确定的位址。
  • 在一次位址轉發整個過程中,隻産生一次網絡請求。而一次位址重寫一般會産生兩次請求。
  • 位址轉發一般發生在同一站點項目内;而位址重寫沒有該限制。
  • 位址轉發到的頁面可以不用全路徑名表示,而位址重寫到的頁面必須使用完整的路徑名表示。
  • 位址轉發過程中,可以将用戶端請求的request範圍内屬性傳遞給新的頁面,但位址重寫不可以
  • 位址轉發的速度較位址重定向快

6.2.2、Rewrite規則

Rewrite規則是學習和使用Nginx伺服器Rewrite功能的基礎,可以借助PCRE實作URI的重寫,并且它還支援Nginx預設變量。Rewrite規則的核心就是PCRE。

6.2.3 If指令

可以在server塊或location塊中配置該指令

if(condition){...}

condition 判斷條件(true/false)

變量名:如果變量的值為空字元串或者以“0”開頭的任意字元串,if指令認為條件為false,其他情況認為條件為true

if($slow) {

    ... #Nginx配置

}

使用“=”(等于)和“!=”(不等于)比較變量和字元串是否相等,相等時if指令認為條件為true,反之為false。

if($request_method=POST) {

     return 405;

}

"~"、“~*”、“!~” 或“!~”連接配接,"~"表示比對過程中對大小寫敏感,"~*"表示比對過程中對大小寫不敏感

if(-f $request_filename){
     ...   #判斷請求的檔案是否存在
}
           
if(!-f $request_filename){
    ...           #判斷請求的檔案是否不存在
}
           

6.2.4、break指令

類似java,跳過

location / {
   if($slow){
     set $id $1             #處于break指令之前,配置有效
     break;
     limit_rate 10k;      #處于break指令之後,配置無效
  }
  ...    #其他Nginx配置,處于break指令所在作用域的上一層作用域,配置有效
}
           

1、return指令

return [text]

return code URL;

return URL;

code:為傳回用戶端的HTTP狀态代碼。

text  : 為傳回給用戶端的響應體内容,支援變量的使用。

URL  為傳回給用戶端URL位址

6.2.5 rewrite指令

該指令通過正規表達式的使用來改變URI,可以同時存在一個或者多個指令,按照順序依次對URL進行比對和處理

文法:rewrite regex replacement [flag]

regex,用于比對URI的正規表達式。使用括号“()”标記要截取的内容

replacement. 比對成功後用于替換URI中被截斷内容的字元串。預設情況下,如果該字元串是由“http://”或者“https://”開頭的,則不會繼續向下對URI進行其他處理,而直接将重寫後的URI傳回給用戶端。

flag 用來設定rewrite對URI的處理行為,可以為以下标志中一個:

last : 終止繼續在本location塊中處理接收到的URI,并将此處重寫的URI作為一個新的URI,使用各location塊進行處理。該标志将重寫後的URI重新在server塊中執行,為重寫後的URI提供了轉入到其他location塊的機會。

break: 此處重寫的URI作為一個新的URI,在本塊中繼續進行處理。該标志将重寫後的位址在目前的location塊中執行。不會将新的URI轉向到其他location塊。

redirect 将重寫後的URI傳回給用戶端,狀态代碼為302,指明是臨時重定向URI,主要用在replacement變量不是以“http://” 或者"https://"開頭的情況下

permanent ,将重寫後的URI傳回給用戶端,狀态代碼為301,指明是永久重定向URI。

6.2.6、rewrite_log指令

該指令配置是否開啟URL重寫日志的輸出功能

Rewrite_log on | off   

預設值為off,如果配置為開啟(on) URL重寫的相關日志将以notice級别輸出到error_log指令配置的日志檔案中。

6.2.7、set指令

指令用于設定一個新的變量

set variable value

variable 為變量的名稱。注意要用$作為變量的第一個字元,且變量不能與Nginx伺服器預設的全局變量同名

value 為變量的值,可以是字元串,其他變量或變量的組合等。

6.2.8、uninitialized_variable_warn指令

該指令用于配置使用為初始化的變量時,是否記錄警告日志

uninitialized_variable_warn on | off

6.2.9、Rewrite常用全局變量

$args  : 變量中存放了請求URL中的請求指令。比如http://www.myweb.name/server/source? arg1=value1&arg2=value2中的“arg1=value1&arg2=value2”

$remote_addr 變量中存放了用戶端的位址

$remote_port 變量中存放了用戶端與伺服器建立的連接配接的端口号

6.3、Rewrite的使用

6.3.1、域名跳轉

#例子1
...
server
{
  listen 80;
  server_name jump.myweb.name;
  rewrite ^/ http://www.myweb.info/;   #域名跳轉
  ...

}
...
#例子2

... 
server
{
	listen 80;
	server_name jump.myweb.name jump.myweb.info;
	if($host ~ myweb\.info)      #注意正在表達式中對點号要用于\進行轉義
	{
		rewrite ^(.*) http://jump.myweb.name$1 permanent;  #多域名跳轉
	}
	...
}
...
#例子3
...
server
{
	listen 80;
	server_name jump1.myweb.name jump2.myweb.name;
	if($http_host ~* ^(.*)\.myweb\.name$)
	{
		rewrite ^(.*) http://jump.myweb.name$1;    #三級域名跳轉
		break;
	}
	....

}
...
           

在例子1中,用戶端通路http://jump.myweb.name時,URL将被Nginx伺服器重寫為http://jump.myweb.info,用戶端得到的資料其實是由http://jump.myweb.info響應的。例子2中,用戶端通路http://jump.myweb.info/reqsource時,URL将被Nginx伺服器重寫為http://jump.myweb.name/reqsource.用戶端得到的資料實際上是由http://jump.myweb.name響應的,在例子3中,用戶端通路http://jump1.myweb.name/reqsource或者 http://jump2.myweb.name/reqsource, URL 都将被Nginx伺服器重寫為http://jump.myweb.name/reqsource.實作了三級域名跳轉。

6.3.2、域名鏡像

鏡像網站是指将一個完全相同的網站分别放置到幾個伺服器上,并分别使用獨立的URL,其中一個伺服器上的網站叫主站,其他的為鏡像網站。

...
server
{
  ...
  listen 80;
  server_name mirror1.myweb.name;
  rewrite ^(.*) http://jump1.myweb.name$1 last;
}
server
{
   ...
   listen 81;
   server_name mirror2.myweb.name;
   rewrite ^(.*) http://jump2.myweb.name$1 last;
}
.....
           

6.3.3、獨立域名

server {
   ... 
   listen 80;
   server_name bbs.myweb.name;
   rewrite ^(.*) http://www.myweb.name/bbs$1 last;
   break;
}

server 
{
  ...
  server_name home.myweb.name;
  rewrite ^(.*) http://www.myweb.name/home$1 last;
  break;
}
...
           

6.3.4、目錄自動添加"/"

達到輸入www.myweb.name,進入index.html    直接通路, /index.html

如果是二級目錄下 例如 在通路http://www.myweb.name/bbs/index.html .如果将URL省略"http://www.myweb.name/bbs/"是可以通路,但是少了最後的"/"是不能通路的。

如果自動加上“/”

server {
	...
	listen 81;
	server_name www.myweb.name;
	location ^~ /bbs
	{
		...
		if(-d $request_filename){
			rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent;
		}
	}
}
           

6.3.5 目錄合并

多級目錄很難被通路到(不利于檢索)

例如 【root】/server/12/34/56/78/9.htm

server
{
	...
	listen 80;
	server_name www.myweb.name;
	locaton ^~ /server
	{
		...
		rewrite ^/server-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)\.htm $
		/server/$1/$2/$3/$4/$5.html last;
	}
}
...
           

用戶端輸入"http://www.myweb.name/server-12-34-56-78-9.htm" 即可通路到9.htm這個資源檔案

6.3.6、防盜鍊

盜鍊 給原網站所在伺服器造成額外負擔的非法行為。 例如查詢圖檔來自其他伺服器的

文法:

valid_referers none | blocked | server_names | String ...;

none 檢測Referer頭域不存在的情況

blocked  檢測Referer頭域的值被防火牆或代理伺服器删除或僞裝的情況。這種情況下,該頭域的值不是以“https://” 或“”http://“”開頭

server_names 設定一個或多個URL,檢測Referer頭域的值是否是這些URL中某個。

實作盜鍊有兩種方式,一種是根據請求資源的資源類型。一種是根據請求的目錄

根據請求資源的資源類型

server
{
	...
	listen 80;
	server_name www.myweb.name;
	location ~* ^.+\.(gif|jpg|png|swf|flv|rar|zip)$
	{
		...
		valid_referers none blocked server_name *. myweb.name;
		if($invalid_referer){
			rewrite ^/ http://www.myweb.com/images/forbidden.png;
		}
	}
}
...
           

根據請求的目錄

server
{
	...
	listen 80;
	server_name www.myweb.name;
	location /file/
	{
		...
		root /server/file/;
		valid_referers none blocked server_name *. myweb.name;
		if($invalid_referer){
			rewrite ^/ http://www.myweb.com/images/forbidden.png;
		}
	}
}
...
           

繼續閱讀