談談 Nginx 那點事【二】


前言

在上一講 談談 Nginx 那點事【一】 中,介紹了Nginx的安裝及基本結構,今天將工作中Nginx的一些配置,及常用的場景做一些總結。

這一講總結的內容主要是關於Nginx服務配置、靜態資源部署、以及強大的 Rewrite功能配置及其常用的場景。

Nginx服務器基礎配置實例

前面我們已經對Nginx服務器默認配置文件的結構和涉及的基本指令做了詳細的闡述。通過這些指令的合理配置,我們就可以讓一台Nginx服務器正常工作,並且提供基本的web服務器功能。

接下來我們將通過一個比較完整和最簡單的基礎配置實例,來鞏固下前面所學習的指令及其配置。

需求如下:

(1)有如下訪問:
	http://192.168.200.133:8081/server1/location1
		訪問的是:index_sr1_location1.html
	http://192.168.200.133:8081/server1/location2
		訪問的是:index_sr1_location2.html
	http://192.168.200.133:8082/server2/location1
		訪問的是:index_sr2_location1.html
	http://192.168.200.133:8082/server2/location2
		訪問的是:index_sr2_location2.html
(2)如果訪問的資源不存在,
	返回自定義的404頁面
(3)將/server1和/server2的配置使用不同的配置文件分割
	將文件放到/home/www/conf.d目錄下,然后使用include進行合並
(4)為/server1和/server2各自創建一個訪問日志文件

准備相關文件,目錄如下:

配置的內容如下:


##全局塊 begin##
#配置允許運行Nginx工作進程的用戶和用戶組
user www;
#配置運行Nginx進程生成的worker進程數
worker_processes 2;
#配置Nginx服務器運行對錯誤日志存放的路徑
error_log logs/error.log;
#配置Nginx服務器允許時記錄Nginx的master進程的PID文件路徑和名稱
pid logs/nginx.pid;
#配置Nginx服務是否以守護進程方法啟動
#daemon on;
##全局塊 end##

##events塊 begin##
events{
	#設置Nginx網絡連接序列化
	accept_mutex on;
	#設置Nginx的worker進程是否可以同時接收多個請求
	multi_accept on;
	#設置Nginx的worker進程最大的連接數
	worker_connections 1024;
	#設置Nginx使用的事件驅動模型
	use epoll;
}
##events塊 end##
##http塊 start##
http{
	#定義MIME-Type
	include mime.types;
	default_type application/octet-stream;
	#配置允許使用sendfile方式運輸
	sendfile on;
	#配置連接超時時間
	keepalive_timeout 65;
	#配置請求處理日志格式
	log_format server1 '===>server1 access log';
	log_format server2 '===>server2 access log';
	##server塊 開始##
	include /home/www/conf.d/*.conf;
	##server塊 結束##
}
##http塊 end##

server1.conf

server{
		#配置監聽端口和主機名稱
		listen 8081;
		server_name localhost;
		#配置請求處理日志存放路徑
		access_log /home/www/myweb/server1/logs/access.log server1;
		#配置錯誤頁面
		error_page 404 /404.html;
		#配置處理/server1/location1請求的location
		location /server1/location1{
			root /home/www/myweb;
			index index_sr1_location1.html;
		}
		#配置處理/server1/location2請求的location
		location /server1/location2{
			root /home/www/myweb;
			index index_sr1_location2.html;
		}
		#配置錯誤頁面轉向
		location = /404.html {
			root /home/www/myweb;
			index 404.html;
		}
}

server2.conf

server{
		#配置監聽端口和主機名稱
		listen 8082;
		server_name localhost;
		#配置請求處理日志存放路徑
		access_log /home/www/myweb/server2/logs/access.log server2;
		#配置錯誤頁面,對404.html做了定向配置
		error_page 404 /404.html;
		#配置處理/server1/location1請求的location
		location /server2/location1{
			root /home/www/myweb;
			index index_sr2_location1.html;
		}
		#配置處理/server2/location2請求的location
		location /server2/location2{
			root /home/www/myweb;
			index index_sr2_location2.html;
		}
		#配置錯誤頁面轉向
		location = /404.html {
			root /home/www/myweb;
			index 404.html;
		}
	}

訪問測試:

Nginx服務操作的問題

經過前面的操作,我們會發現,如果想要啟動、關閉或重新加載nginx配置文件,都需要先進入到nginx的安裝目錄的sbin目錄,然后使用nginx的二級制可執行文件來操作,相對來說操作比較繁瑣,這塊該如何優化?另外如果我們想把Nginx設置成隨着服務器啟動就自動完成啟動操作,又該如何來實現?這就需要用到接下來我們要講解的兩個知識點:

Nginx配置成系統服務
Nginx命令配置到系統環境

Nginx配置成系統服務

把Nginx應用服務設置成為系統服務,方便對Nginx服務的啟動和停止等相關操作,具體實現步驟:

(1) 在/usr/lib/systemd/system目錄下添加nginx.service,內容如下:

vim /usr/lib/systemd/system/nginx.service
[Unit]
Description=nginx web service
Documentation=http://nginx.org/en/docs/
After=network.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s stop
PrivateTmp=true

[Install]
WantedBy=default.target

(2)添加完成后如果權限有問題需要進行權限設置

chmod 755 /usr/lib/systemd/system/nginx.service

(3)使用系統命令來操作Nginx服務

啟動: systemctl start nginx
停止: systemctl stop nginx
重啟: systemctl restart nginx
重新加載配置文件: systemctl reload nginx
查看nginx狀態: systemctl status nginx
開機啟動: systemctl enable nginx

Nginx命令配置到系統環境

前面我們介紹過Nginx安裝目錄下的二級制可執行文件nginx的很多命令,要想使用這些命令前提是需要進入sbin目錄下才能使用,很不方便,如何去優化,我們可以將該二進制可執行文件加入到系統的環境變量,這樣的話在任何目錄都可以使用nginx對應的相關命令。具體實現步驟如下:

演示可刪除

/usr/local/nginx/sbin/nginx -V
cd /usr/local/nginx/sbin  nginx -V
如何優化???

(1)修改/etc/profile文件

vim /etc/profile
在最后一行添加
export PATH=$PATH:/usr/local/nginx/sbin

(2)使之立即生效

source /etc/profile

(3)執行nginx命令

nginx -V

Nginx靜態資源部署

Nginx靜態資源概述

上網去搜索訪問資源對於我們來說並不陌生,通過瀏覽器發送一個HTTP請求實現從客戶端發送請求到服務器端獲取所需要內容后並把內容回顯展示在頁面的一個過程。這個時候,我們所請 求的內容就分為兩種類型,一類是靜態資源、一類是動態資源。
靜態資源即指在服務器端真實存在並且能直接拿來展示的一些文件,比如常見的html頁面、css文件、js文件、圖 片、視頻等資源;
動態資源即指在服務器端真實存在但是要想獲取需要經過一定的業務邏輯處理,根據不同的條件展示在頁面不同這 一部分內容,比如說報表數據展示、根據當前登錄用戶展示相關具體數據等資源;

Nginx處理靜態資源的內容,我們需要考慮下面這幾個問題:

(1)靜態資源的配置指令
(2)靜態資源的配置優化
(3)靜態資源的壓縮配置指令
(4)靜態資源的緩存處理
(5)靜態資源的訪問控制,包括跨域問題和防盜鏈問題

Nginx靜態資源的配置指令

listen指令

listen:用來配置監聽端口。

語法 listen address[:port] [default_server]...;
listen port [default_server]...;
默認值 listen *:80 | *:8000
位置 server

listen的設置比較靈活,我們通過幾個例子來把常用的設置方式熟悉下:

listen 127.0.0.1:8000; // listen localhost:8000 監聽指定的IP和端口
listen 127.0.0.1;	監聽指定IP的所有端口
listen 8000;	監聽指定端口上的連接
listen *:8000;	監聽指定端口上的連接

default_server屬性是標識符,用來將此虛擬主機設置成默認主機。所謂的默認主機指的是如果沒有匹配到對應的address:port,則會默認執行的。如果不指定默認使用的是第一個server。

server{
	listen 8080;
	server_name 127.0.0.1;
	location /{
		root html;
		index index.html;
	}
}
server{
	listen 8080 default_server;
	server_name localhost;
	default_type text/plain;
	return 444 'This is a error request';
}

server_name指令

server_name:用來設置虛擬主機服務名稱。

127.0.0.1 、 localhost 、域名[www.baidu.com | www.jd.com]

語法 server_name name ...;
name可以提供多個中間用空格分隔
默認值 server_name "";
位置 server

關於server_name的配置方式有三種,分別是:

精確匹配
通配符匹配
正則表達式匹配

配置方式一:精確匹配

如:

server {
	listen 80;
	server_name www.itcast.cn www.itheima.cn;
	...
}

補充小知識點:

hosts是一個沒有擴展名的系統文件,可以用記事本等工具打開,其作用就是將一些常用的網址域名與其對應的IP地址建立一個關聯“數據庫”,當用戶在瀏覽器中輸入一個需要登錄的網址時,系統會首先自動從hosts文件中尋找對應的IP地址,一旦找到,系統會立即打開對應網頁,如果沒有找到,則系統會再將網址提交DNS域名解析服務器進行IP地址的解析。

windows:C:\Windows\System32\drivers\etc

centos:/etc/hosts

因為域名是要收取一定的費用,所以我們可以使用修改hosts文件來制作一些虛擬域名來使用。需要修改 /etc/hosts文件來添加

vim /etc/hosts
127.0.0.1 www.itcast.cn
127.0.0.1 www.itheima.cn

配置方式二:使用通配符配置

server_name中支持通配符"*",但需要注意的是通配符不能出現在域名的中間,只能出現在首段或尾段,如:

server {
	listen 80;
	server_name  *.itcast.cn	www.itheima.*;
	# www.itcast.cn abc.itcast.cn www.itheima.cn www.itheima.com
	...
}

下面的配置就會報錯

server {
	listen 80;
	server_name  www.*.cn www.itheima.c*
	...
}

配置三:使用正則表達式配置

server_name中可以使用正則表達式,並且使用~作為正則表達式字符串的開始標記。

常見的正則表達式

代碼 說明
^ 匹配搜索字符串開始位置
$ 匹配搜索字符串結束位置
. 匹配除換行符\n之外的任何單個字符
\ 轉義字符,將下一個字符標記為特殊字符
[xyz] 字符集,與任意一個指定字符匹配
[a-z] 字符范圍,匹配指定范圍內的任何字符
\w 與以下任意字符匹配 A-Z a-z 0-9 和下划線,等效於[A-Za-z0-9_]
\d 數字字符匹配,等效於[0-9]
{n} 正好匹配n次
{n,} 至少匹配n次
{n,m} 匹配至少n次至多m次
* 零次或多次,等效於{0,}
+ 一次或多次,等效於{1,}
? 零次或一次,等效於{0,1}

配置如下:

server{
        listen 80;
        server_name ~^www\.(\w+)\.com$;
        default_type text/plain;
        return 200 $1  $2 ..;
}
注意 ~后面不能加空格,括號可以取值
匹配執行順序

由於server_name指令支持通配符和正則表達式,因此在包含多個虛擬主機的配置文件中,可能會出現一個名稱被多個虛擬主機的server_name匹配成功,當遇到這種情況,當前的請求交給誰來處理呢?

server{
	listen 80;
	server_name ~^www\.\w+\.com$;
	default_type text/plain;
	return 200 'regex_success';
}

server{
	listen 80;
	server_name www.itheima.*;
	default_type text/plain;
	return 200 'wildcard_after_success';
}

server{
	listen 80;
	server_name *.itheima.com;
	default_type text/plain;
	return 200 'wildcard_before_success';
}

server{
	listen 80;
	server_name www.itheima.com;
	default_type text/plain;
	return 200 'exact_success';
}

server{
	listen 80 default_server;
	server_name _;
	default_type text/plain;
	return 444 'default_server not found server';
}

結論:

exact_success
wildcard_before_success
wildcard_after_success
regex_success
default_server not found server!!
No1:准確匹配server_name

No2:通配符在開始時匹配server_name成功

No3:通配符在結束時匹配server_name成功

No4:正則表達式匹配server_name成功

No5:被默認的default_server處理,如果沒有指定默認找第一個server

location指令

server{
	listen 80;
	server_name localhost;
	location / {
	
	}
	location /abc{
	
	}
	...
}

location:用來設置請求的URI

語法 location [ = | ~ | ~* | ^~ |@ ] uri{...}
默認值
位置 server,location

uri變量是待匹配的請求字符串,可以不包含正則表達式,也可以包含正則表達式,那么nginx服務器在搜索匹配location的時候,是先使用不包含正則表達式進行匹配,找到一個匹配度最高的一個,然后在通過包含正則表達式的進行匹配,如果能匹配到直接訪問,匹配不到,就使用剛才匹配度最高的那個location來處理請求。

屬性介紹:

不帶符號,要求必須以指定模式開始

server {
	listen 80;
	server_name 127.0.0.1;
	location /abc{
		default_type text/plain;
		return 200 "access success";
	}
}
以下訪問都是正確的
http://192.168.200.133/abc
http://192.168.200.133/abc?p1=TOM
http://192.168.200.133/abc/
http://192.168.200.133/abcdef

= : 用於不包含正則表達式的uri前,必須與指定的模式精確匹配

server {
	listen 80;
	server_name 127.0.0.1;
	location =/abc{
		default_type text/plain;
		return 200 "access success";
	}
}
可以匹配到
http://192.168.200.133/abc
http://192.168.200.133/abc?p1=TOM
匹配不到
http://192.168.200.133/abc/
http://192.168.200.133/abcdef

~ : 用於表示當前uri中包含了正則表達式,並且區分大小寫
~*: 用於表示當前uri中包含了正則表達式,並且不區分大小寫

換句話說,如果uri包含了正則表達式,需要用上述兩個符合來標識

server {
	listen 80;
	server_name 127.0.0.1;
	location ~^/abc\w${
		default_type text/plain;
		return 200 "access success";
	}
}
server {
	listen 80;
	server_name 127.0.0.1;
	location ~*^/abc\w${
		default_type text/plain;
		return 200 "access success";
	}
}

^~: 用於不包含正則表達式的uri前,功能和不加符號的一致,唯一不同的是,如果模式匹配,那么就停止搜索其他模式了。

server {
	listen 80;
	server_name 127.0.0.1;
	location ^~/abc{
		default_type text/plain;
		return 200 "access success";
	}
}

設置請求資源的目錄root / alias

root:設置請求的根目錄

語法 root path;
默認值 root html;
位置 http、server、location

path為Nginx服務器接收到請求以后查找資源的根目錄路徑。

alias:用來更改location的URI

語法 alias path;
默認值
位置 location

path為修改后的根路徑。

以上兩個指令都可以來指定訪問資源的路徑,那么這兩者之間的區別是什么?

舉例說明:

(1)在/usr/local/nginx/html目錄下創建一個 images目錄,並在目錄下放入一張圖片mv.png圖片

location /images {
	root /usr/local/nginx/html;
}

訪問圖片的路徑為:

http://192.168.200.133/images/mv.png

(2)如果把root改為alias

location /images {
	alias /usr/local/nginx/html;
}

再次訪問上述地址,頁面會出現404的錯誤,查看錯誤日志會發現是因為地址不對,所以驗證了:

root的處理結果是: root路徑+location路徑
/usr/local/nginx/html/images/mv.png
alias的處理結果是:使用alias路徑替換location路徑
/usr/local/nginx/html/images

需要在alias后面路徑改為

location /images {
	alias /usr/local/nginx/html/images;
}

(3)如果location路徑是以/結尾,則alias也必須是以/結尾,root沒有要求

將上述配置修改為

location /images/ {
	alias /usr/local/nginx/html/images;
}

訪問就會出問題,查看錯誤日志還是路徑不對,所以需要把alias后面加上 /

小結:

root的處理結果是: root路徑+location路徑
alias的處理結果是:使用alias路徑替換location路徑
alias是一個目錄別名的定義,root則是最上層目錄的含義。
如果location路徑是以/結尾,則alias也必須是以/結尾,root沒有要求

index指令

index:設置網站的默認首頁

語法 index file ...;
默認值 index index.html;
位置 http、server、location

index后面可以跟多個設置,如果訪問的時候沒有指定具體訪問的資源,則會依次進行查找,找到第一個為止。

舉例說明:

location / {
	root /usr/local/nginx/html;
	index index.html index.htm;
}
訪問該location的時候,可以通過 http://ip:port/,地址后面如果不添加任何內容,則默認依次訪問index.html和index.htm,找到第一個來進行返回

error_page指令

error_page:設置網站的錯誤頁面

語法 error_page code ... [=[response]] uri;
默認值
位置 http、server、location......

當出現對應的響應code后,如何來處理。

舉例說明:

(1)可以指定具體跳轉的地址

server {
	error_page 404 http://www.itcast.cn;
}

(2)可以指定重定向地址

server{
	error_page 404 /50x.html;
	error_page 500 502 503 504 /50x.html;
	location =/50x.html{
		root html;
	}
}

(3)使用location的@符合完成錯誤信息展示

server{
	error_page 404 @jump_to_error;
	location @jump_to_error {
		default_type text/plain;
		return 404 'Not Found Page...';
	}
}

可選項=[response]的作用是用來將相應代碼更改為另外一個

server{
	error_page 404 =200 /50x.html;
	location =/50x.html{
		root html;
	}
}
這樣的話,當返回404找不到對應的資源的時候,在瀏覽器上可以看到,最終返回的狀態碼是200,這塊需要注意下,編寫error_page后面的內容,404后面需要加空格,200前面不能加空格

靜態資源優化配置語法

Nginx對靜態資源如何進行優化配置。這里從三個屬性配置進行優化:

sendfile on;
tcp_nopush on;
tcp_nodeplay on;

(1)sendfile,用來開啟高效的文件傳輸模式。

語法 sendfile on |off;
默認值 sendfile off;
位置 http、server、location...

請求靜態資源的過程:客戶端通過網絡接口向服務端發送請求,操作系統將這些客戶端的請求傳遞給服務器端應用程序,服務器端應用程序會處理這些請求,請求處理完成以后,操作系統還需要將處理得到的結果通過網絡適配器傳遞回去。

如:

server {
	listen 80;
	server_name localhost;
	location / {
		root html;
		index index.html;
	}
}
在html目錄下有一個welcome.html頁面,訪問地址
http://192.168.200.133/welcome.html

(2)tcp_nopush:該指令必須在sendfile打開的狀態下才會生效,主要是用來提升網絡包的傳輸'效率'

語法 tcp_nopush on|off;
默認值 tcp_nopush off;
位置 http、server、location

(3)tcp_nodelay:該指令必須在keep-alive連接開啟的情況下才生效,來提高網絡包傳輸的'實時性'

語法 tcp_nodelay on|off;
默認值 tcp_nodelay on;
位置 http、server、location

經過剛才的分析,"tcp_nopush"和”tcp_nodelay“看起來是"互斥的",那么為什么要將這兩個值都打開,這個大家需要知道的是在linux2.5.9以后的版本中兩者是可以兼容的,三個指令都開啟的好處是,sendfile可以開啟高效的文件傳輸模式,tcp_nopush開啟可以確保在發送到客戶端之前數據包已經充分“填滿”, 這大大減少了網絡開銷,並加快了文件發送的速度。 然后,當它到達最后一個可能因為沒有“填滿”而暫停的數據包時,Nginx會忽略tcp_nopush參數, 然后,tcp_nodelay強制套接字發送數據。由此可知,TCP_NOPUSH可以與TCP_NODELAY一起設置,它比單獨配置TCP_NODELAY具有更強的性能。所以我們可以使用如下配置來優化Nginx靜態資源的處理

sendfile on;
tcp_nopush on;
tcp_nodelay on;

Nginx靜態資源壓縮實戰

經過上述內容的優化,我們再次思考一個問題,假如在滿足上述優化的前提下,我們傳送一個1M的數據和一個10M的數據那個效率高?,答案顯而易見,傳輸內容小,速度就會快。那么問題又來了,同樣的內容,如果把大小降下來,我們腦袋里面要蹦出一個詞就是"壓縮",接下來,我們來學習Nginx的靜態資源壓縮模塊。

在Nginx的配置文件中可以通過配置gzip來對靜態資源進行壓縮,相關的指令可以配置在http塊、server塊和location塊中,Nginx可以通過

ngx_http_gzip_module模塊			 #安裝nginx默認配置的
ngx_http_gzip_static_module模塊	 #需要手動安裝
ngx_http_gunzip_module模塊		 #需要手動安裝

對這些指令進行解析和處理。

接下來我們從以下內容進行學習

(1)Gzip各模塊支持的配置指令
(2)Gzip壓縮功能的配置
(3)Gzip和sendfile的沖突解決
(4)瀏覽器不支持Gzip的解決方案

Gzip模塊配置指令

接下來所學習的指令都來自ngx_http_gzip_module模塊,該模塊會在nginx安裝的時候內置到nginx的安裝環境中,也就是說我們可以直接使用這些指令。

  1. gzip指令:該指令用於開啟或者關閉gzip功能
語法 gzip on|off;
默認值 gzip off;
位置 http、server、location...

注意只有該指令為打開狀態,下面的指令才有效果

http{
   gzip on;
}
  1. gzip_types指令:該指令可以根據響應頁的MIME類型選擇性地開啟Gzip壓縮功能
語法 gzip_types mime-type ...;
默認值 gzip_types text/html;
位置 http、server、location

所選擇的值可以從mime.types文件中進行查找,也可以使用"*"代表所有。

http{
	gzip_types application/javascript;
}
  1. gzip_comp_level指令:該指令用於設置Gzip壓縮程度,級別從1-9, 1表示壓縮程度最低,壓縮效率最高,9剛好相反,壓縮程度最高,但是效率最低最費時間。
語法 gzip_comp_level level;
默認值 gzip_comp_level 1;
位置 http、server、location
http{
	gzip_comp_level 6;
}
  1. gzip_vary指令:該指令用於設置使用Gzip進行壓縮發送是否攜帶“Vary:Accept-Encoding”頭域的響應頭部。主要是告訴接收方,所發送的數據經過了Gzip壓縮處理
語法 gzip_vary on|off;
默認值 gzip_vary off;
位置 http、server、location

  1. gzip_buffers指令:該指令用於處理請求壓縮的緩沖區數量和大小。
語法 gzip_buffers number size;
默認值 gzip_buffers 32 4k|16 8k;
位置 http、server、location

其中number:指定Nginx服務器向系統申請緩存空間個數,size指的是每個緩存空間的大小。主要實現的是申請number個每個大小為size的內存空間。這個值的設定一般會和服務器的操作系統有關,所以建議此項不設置,使用默認值即可。

gzip_buffers 4 16K;	  #緩存空間大小
  1. gzip_disable指令:針對不同種類客戶端發起的請求,可以選擇性地開啟和關閉Gzip功能。
語法 gzip_disable regex ...;
默認值
位置 http、server、location

regex:根據客戶端的瀏覽器標志(user-agent)來設置,支持使用正則表達式。指定的瀏覽器標志不使用Gzip.該指令一般是用來排除一些明顯不支持Gzip的瀏覽器。

gzip_disable "MSIE [1-6]\.";
  1. gzip_http_version指令:針對不同的HTTP協議版本,可以選擇性地開啟和關閉Gzip功能。
語法 gzip_http_version 1.0|1.1;
默認值 gzip_http_version 1.1;
位置 http、server、location

該指令是指定使用Gzip的HTTP最低版本,該指令一般采用默認值即可。

  1. gzip_min_length指令:該指令針對傳輸數據的大小,可以選擇性地開啟和關閉Gzip功能
語法 gzip_min_length length;
默認值 gzip_min_length 20;
位置 http、server、location
nignx計量大小的單位:bytes[字節] / kb[千字節] / M[兆]
例如: 1024 / 10k|K / 10m|M

Gzip壓縮功能對大數據的壓縮效果明顯,但是如果要壓縮的數據比較小的化,可能出現越壓縮數據量越大的情況,因此我們需要根據響應內容的大小來決定是否使用Gzip功能,響應頁面的大小可以通過頭信息中的Content-Length來獲取。但是如何使用了Chunk編碼動態壓縮,該指令將被忽略。建議設置為1K或以上。

  1. gzip_proxied指令:該指令設置是否對服務端返回的結果進行Gzip壓縮。
語法 gzip_proxied off|expired|no-cache|
no-store|private|no_last_modified|no_etag|auth|any;
默認值 gzip_proxied off;
位置 http、server、location

off - 關閉Nginx服務器對后台服務器返回結果的Gzip壓縮
expired - 啟用壓縮,如果header頭中包含 "Expires" 頭信息
no-cache - 啟用壓縮,如果header頭中包含 "Cache-Control:no-cache" 頭信息
no-store - 啟用壓縮,如果header頭中包含 "Cache-Control:no-store" 頭信息
private - 啟用壓縮,如果header頭中包含 "Cache-Control:private" 頭信息
no_last_modified - 啟用壓縮,如果header頭中不包含 "Last-Modified" 頭信息
no_etag - 啟用壓縮 ,如果header頭中不包含 "ETag" 頭信息
auth - 啟用壓縮 , 如果header頭中包含 "Authorization" 頭信息
any - 無條件啟用壓縮

Gzip壓縮功能的實例配置

gzip on;  			  #開啟gzip功能
gzip_types *;		  #壓縮源文件類型,根據具體的訪問資源類型設定
gzip_comp_level 6;	  #gzip壓縮級別
gzip_min_length 1024; #進行壓縮響應頁面的最小長度,content-length
gzip_buffers 4 16K;	  #緩存空間大小
gzip_http_version 1.1; #指定壓縮響應所需要的最低HTTP請求版本
gzip_vary  on;		  #往頭信息中添加壓縮標識
gzip_disable "MSIE [1-6]\."; #對IE6以下的版本都不進行壓縮
gzip_proxied  off; #nginx作為反向代理壓縮服務端返回數據的條件

這些配置在很多地方可能都會用到,所以我們可以將這些內容抽取到一個配置文件中,然后通過include指令把配置文件再次加載到nginx.conf配置文件中,方法使用。

nginx_gzip.conf

gzip on;
gzip_types *;
gzip_comp_level 6;
gzip_min_length 1024;
gzip_buffers 4 16K;
gzip_http_version 1.1;
gzip_vary  on;
gzip_disable "MSIE [1-6]\.";
gzip_proxied  off;

nginx.conf

include nginx_gzip.conf

Gzip和sendfile共存問題

前面在講解sendfile的時候,提到過,開啟sendfile以后,在讀取磁盤上的靜態資源文件的時候,可以減少拷貝的次數,可以不經過用戶進程將靜態文件通過網絡設備發送出去,但是Gzip要想對資源壓縮,是需要經過用戶進程進行操作的。所以如何解決兩個設置的共存問題。

可以使用ngx_http_gzip_static_module模塊的gzip_static指令來解決。

gzip_static指令

gzip_static: 檢查與訪問資源同名的.gz文件時,response中以gzip相關的header返回.gz文件的內容。

語法 gzip_static on | off | always;
默認值 gzip_static off;
位置 http、server、location

添加上述命令后,會報一個錯誤,unknown directive "gzip_static"主要的原因是Nginx默認是沒有添加ngx_http_gzip_static_module模塊。如何來添加?

添加模塊到Nginx的實現步驟

(1)查詢當前Nginx的配置參數

nginx -V

(2)將nginx安裝目錄下sbin目錄中的nginx二進制文件進行更名

cd /usr/local/nginx/sbin
mv nginx nginxold

(3) 進入Nginx的安裝目錄

cd /root/nginx/core/nginx-1.16.1

(4)執行make clean清空之前編譯的內容

make clean

(5)使用configure來配置參數

./configure --with-http_gzip_static_module

(6)使用make命令進行編譯

make

(7) 將objs目錄下的nginx二進制執行文件移動到nginx安裝目錄下的sbin目錄中

mv objs/nginx /usr/local/nginx/sbin

(8)執行更新命令

make upgrade
gzip_static測試使用

(1)直接訪問http://192.168.200.133/jquery.js

(2)使用gzip命令進行壓縮

cd /usr/local/nginx/html
gzip jquery.js

(3)再次訪問http://192.168.200.133/jquery.js

靜態資源的緩存處理

什么是緩存

緩存(cache),原始意義是指訪問速度比一般隨機存取存儲器(RAM)快的一種高速存儲器,通常它不像系統主存那樣使用DRAM技術,而使用昂貴但較快速的SRAM技術。緩存的設置是所有現代計算機系統發揮高性能的重要因素之一。

什么是web緩存

Web緩存是指一個Web資源(如html頁面,圖片,js,數據等)存在於Web服務器和客戶端(瀏覽器)之間的副本。緩存會根據進來的請求保存輸出內容的副本;當下一個請求來到的時候,如果是相同的URL,緩存會根據緩存機制決定是直接使用副本響應訪問請求,還是向源服務器再次發送請求。比較常見的就是瀏覽器會緩存訪問過網站的網頁,當再次訪問這個URL地址的時候,如果網頁沒有更新,就不會再次下載網頁,而是直接使用本地緩存的網頁。只有當網站明確標識資源已經更新,瀏覽器才會再次下載網頁

web緩存的種類

客戶端緩存
	瀏覽器緩存
服務端緩存
	Nginx / Redis / Memcached等

瀏覽器緩存

是為了節約網絡的資源加速瀏覽,瀏覽器在用戶磁盤上對最近請求過的文檔進行存儲,當訪問者再次請求這個頁面時,瀏覽器就可以從本地磁盤顯示文檔,這樣就可以加速頁面的閱覽.

為什么要用瀏覽器緩存

成本最低的一種緩存實現
減少網絡帶寬消耗
降低服務器壓力
減少網絡延遲,加快頁面打開速度

瀏覽器緩存的執行流程

HTTP協議中和頁面緩存相關的字段,我們先來認識下:

header 說明
Expires 緩存過期的日期和時間
Cache-Control 設置和緩存相關的配置信息
Last-Modified 請求資源最后修改時間
ETag 請求變量的實體標簽的當前值,比如文件的MD5值

(1)用戶首次通過瀏覽器發送請求到服務端獲取數據,客戶端是沒有對應的緩存,所以需要發送request請求來獲取數據;

(2)服務端接收到請求后,獲取服務端的數據及服務端緩存的允許后,返回200的成功狀態碼並且在響應頭上附上對應資源以及緩存信息;

(3)當用戶再次訪問相同資源的時候,客戶端會在瀏覽器的緩存目錄中查找是否存在響應的緩存文件

(4)如果沒有找到對應的緩存文件,則走(2)步

(5)如果有緩存文件,接下來對緩存文件是否過期進行判斷,過期的判斷標准是(Expires),

(6)如果沒有過期,則直接從本地緩存中返回數據進行展示

(7)如果Expires過期,接下來需要判斷緩存文件是否發生過變化

(8)判斷的標准有兩個,一個是ETag(Entity Tag),一個是Last-Modified

(9)判斷結果是未發生變化,則服務端返回304,直接從緩存文件中獲取數據

(10)如果判斷是發生了變化,重新從服務端獲取數據,並根據緩存協商(服務端所設置的是否需要進行緩存數據的設置)來進行數據緩存。

瀏覽器緩存相關指令

Nginx需要進行緩存相關設置,就需要用到如下的指令

expires指令

expires:該指令用來控制頁面緩存的作用。可以通過該指令控制HTTP應答中的“Expires"和”Cache-Control"

語法 expires [modified] time
expires epoch|max|off;
默認值 expires off;
位置 http、server、location

time:可以整數也可以是負數,指定過期時間,如果是負數,Cache-Control則為no-cache,如果為整數或0,則Cache-Control的值為max-age=time;

epoch: 指定Expires的值為'1 January,1970,00:00:01 GMT'(1970-01-01 00:00:00),Cache-Control的值no-cache

max:指定Expires的值為'31 December2037 23:59:59GMT' (2037-12-31 23:59:59) ,Cache-Control的值為10年

off:默認不緩存。

add_header指令

add_header指令是用來添加指定的響應頭和響應值。

語法 add_header name value [always];
默認值
位置 http、server、location...

Cache-Control作為響應頭信息,可以設置如下值:

緩存響應指令:

Cache-control: must-revalidate
Cache-control: no-cache
Cache-control: no-store
Cache-control: no-transform
Cache-control: public
Cache-control: private
Cache-control: proxy-revalidate
Cache-Control: max-age=<seconds>
Cache-control: s-maxage=<seconds>
指令 說明
must-revalidate 可緩存但必須再向源服務器進行確認
no-cache 緩存前必須確認其有效性
no-store 不緩存請求或響應的任何內容
no-transform 代理不可更改媒體類型
public 可向任意方提供響應的緩存
private 僅向特定用戶返回響應
proxy-revalidate 要求中間緩存服務器對緩存的響應有效性再進行確認
max-age=<秒> 響應最大Age值
s-maxage=<秒> 公共緩存服務器響應的最大Age值

max-age=[秒]:

Nginx的跨域問題解決

這塊內容,我們主要從以下方面進行解決:

什么情況下會出現跨域問題?
實例演示跨域問題
具體的解決方案是什么?

同源策略

瀏覽器的同源策略:是一種約定,是瀏覽器最核心也是最基本的安全功能,如果瀏覽器少了同源策略,則瀏覽器的正常功能可能都會受到影響。

同源: 協議、域名(IP)、端口相同即為同源

http://192.168.200.131/user/1
https://192.168.200.131/user/1
協議不一致,不滿足同源策略

http://192.168.200.131/user/1
http://192.168.200.132/user/1
域名不一致,不滿足同源策略

http://192.168.200.131/user/1
http://192.168.200.131:8080/user/1
端口不一致,不滿足同源策略

http://www.nginx.com/user/1
http://www.nginx.org/user/1
域名不一致,不滿足同源策略

http://192.168.200.131/user/1
http://192.168.200.131:8080/user/1
端口不一致,不滿足同源策略

http://www.nginx.org:80/user/1
http://www.nginx.org/user/1
滿足同源策略

跨域問題

簡單描述下:

有兩台服務器分別為A,B,如果從服務器A的頁面發送異步請求到服務器B獲取數據,如果服務器A和服務器B不滿足同源策略,則就會出現跨域問題。

跨域問題的案例演示

出現跨域問題會有什么效果?,接下來通過一個需求來給大家演示下:

(1)nginx的html目錄下新建一個a.html

<html>
  <head>
        <meta charset="utf-8">
        <title>跨域問題演示</title>
        <script src="jquery.js"></script>
        <script>
            $(function(){
                $("#btn").click(function(){
                        $.get('http://192.168.200.133:8080/getUser',function(data){
                                alert(JSON.stringify(data));
                        });
                });
            });
        </script>
  </head>
  <body>
        <input type="button" value="獲取數據" id="btn"/>
  </body>
</html>

(2)在nginx.conf配置如下內容

server{
        listen  8080;
        server_name localhost;
        location /getUser{
                default_type application/json;
                return 200 '{"id":1,"name":"TOM","age":18}';
        }
}
server{
	listen 	80;
	server_name localhost;
	location /{
		root html;
		index index.html;
	}
}

(3)通過瀏覽器訪問測試

解決方案

使用add_header指令,該指令可以用來添加一些頭信息

語法 add_header name value...
默認值
位置 http、server、location

此處用來解決跨域問題,需要添加兩個頭信息,一個是Access-Control-Allow-Origin,Access-Control-Allow-Methods

Access-Control-Allow-Origin: 直譯過來是允許跨域訪問的源地址信息,可以配置多個(多個用逗號分隔),也可以使用*代表所有源

Access-Control-Allow-Methods:直譯過來是允許跨域訪問的請求方式,值可以為 GET POST PUT DELETE...,可以全部設置,也可以根據需要設置,多個用逗號分隔

具體配置方式

location /getUser{
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE;
    default_type application/json;
    return 200 '{"id":1,"name":"TOM","age":18}';
}

靜態資源防盜鏈

什么是資源盜鏈

資源盜鏈指的是此內容不在自己服務器上,而是通過技術手段,繞過別人的限制將別人的內容放到自己頁面上最終展示給用戶。以此來盜取大網站的空間和流量。簡而言之就是用別人的東西成就自己的網站。

效果演示

京東:https://img14.360buyimg.com/n7/jfs/t1/101062/37/2153/254169/5dcbd410E6d10ba22/4ddbd212be225fcd.jpg

百度:https://pics7.baidu.com/feed/cf1b9d16fdfaaf516f7e2011a7cda1e8f11f7a1a.jpeg?token=551979a23a0995e5e5279b8fa1a48b34&s=BD385394D2E963072FD48543030030BB

我們自己准備一個頁面,在頁面上引入這兩個圖片查看效果

從上面的效果,可以看出來,下面的圖片地址添加了防止盜鏈的功能,京東這邊我們可以直接使用其圖片。

Nginx防盜鏈的實現原理:

了解防盜鏈的原理之前,我們得先學習一個HTTP的頭信息Referer,當瀏覽器向web服務器發送請求的時候,一般都會帶上Referer,來告訴瀏覽器該網頁是從哪個頁面鏈接過來的。

后台服務器可以根據獲取到的這個Referer信息來判斷是否為自己信任的網站地址,如果是則放行繼續訪問,如果不是則可以返回403(服務端拒絕訪問)的狀態信息。

在本地模擬上述的服務器效果:

Nginx防盜鏈的具體實現:

valid_referers:nginx會通就過查看referer自動和valid_referers后面的內容進行匹配,如果匹配到了就將$invalid_referer變量置0,如果沒有匹配到,則將$invalid_referer變量置為1,匹配的過程中不區分大小寫。

語法 valid_referers none|blocked|server_names|string...
默認值
位置 server、location

none: 如果Header中的Referer為空,允許訪問

blocked:在Header中的Referer不為空,但是該值被防火牆或代理進行偽裝過,如不帶"http://" 、"https://"等協議頭的資源允許訪問。

server_names:指定具體的域名或者IP

string: 可以支持正則表達式和*的字符串。如果是正則表達式,需要以~開頭表示,例如

location ~*\.(png|jpg|gif){
           valid_referers none blocked www.baidu.com 192.168.200.222 *.example.com example.*  www.example.org  ~\.google\.;
           if ($invalid_referer){
                return 403;
           }
           root /usr/local/nginx/html;

}

遇到的問題:圖片有很多,該如何批量進行防盜鏈?

針對目錄進行防盜鏈

配置如下:

location /images {
           valid_referers none blocked www.baidu.com 192.168.200.222 *.example.com example.*  www.example.org  ~\.google\.;
           if ($invalid_referer){
                return 403;
           }
           root /usr/local/nginx/html;

}

這樣我們可以對一個目錄下的所有資源進行翻到了操作。

遇到的問題:Referer的限制比較粗,比如隨意加一個Referer,上面的方式是無法進行限制的。那么這個問題改如何解決?

此處我們需要用到Nginx的第三方模塊ngx_http_accesskey_module,第三方模塊如何實現盜鏈,如果在Nginx中使用第三方模塊的功能,這些我們在后面的Nginx的模塊篇再進行詳細的講解。

Rewrite功能配置

Rewrite是Nginx服務器提供的一個重要基本功能,是Web服務器產品中幾乎必備的功能。主要的作用是用來實現URL的重寫。www.jd.com
注意:Nginx服務器的Rewrite功能的實現依賴於PCRE的支持,因此在編譯安裝Nginx服務器之前,需要安裝PCRE庫。Nginx使用的是ngx_http_rewrite_module模塊來解析和處理Rewrite功能的相關配置。

Rewrite的相關命令

set指令
if指令
break指令
return指令
rewrite指令
rewrite_log指令

Rewrite的應用場景

域名跳轉
域名鏡像
獨立域名
目錄自動添加"/"
合並目錄
防盜鏈的實現

Rewrite的相關指令

set指令

該指令用來設置一個新的變量。

語法 set $variable value;
默認值
位置 server、location、if

variable:變量的名稱,該變量名稱要用"$"作為變量的第一個字符,且不要與Nginx服務器預設的全局變量同名。

value:變量的值,可以是字符串、其他變量或者變量的組合等。

Rewrite常用全局變量

變量 說明
$args 變量中存放了請求URL中的請求參數。比如http://192.168.200.133/server?arg1=value1&args2=value2中的"arg1=value1&arg2=value2",功能和$query_string一樣
$http_user_agent 變量存儲的是用戶訪問服務的代理信息(如果通過瀏覽器訪問,記錄的是瀏覽器的相關版本信息)
$host 變量存儲的是訪問服務器的server_name值
$document_uri 變量存儲的是當前訪問地址的URI。比如http://192.168.200.133/server?id=10&name=zhangsan中的"/server",功能和$uri一樣
$document_root 變量存儲的是當前請求對應location的root值,如果未設置,默認指向Nginx自帶html目錄所在位置
$content_length 變量存儲的是請求頭中的Content-Length的值
$content_type 變量存儲的是請求頭中的Content-Type的值
$http_cookie 變量存儲的是客戶端的cookie信息,可以通過add_header Set-Cookie 'cookieName=cookieValue'來添加cookie數據
$limit_rate 變量中存儲的是Nginx服務器對網絡連接速率的限制,也就是Nginx配置中對limit_rate指令設置的值,默認是0,不限制。
$remote_addr 變量中存儲的是客戶端的IP地址
$remote_port 變量中存儲了客戶端與服務端建立連接的端口號
$remote_user 變量中存儲了客戶端的用戶名,需要有認證模塊才能獲取
$scheme 變量中存儲了訪問協議
$server_addr 變量中存儲了服務端的地址
$server_name 變量中存儲了客戶端請求到達的服務器的名稱
$server_port 變量中存儲了客戶端請求到達服務器的端口號
$server_protocol 變量中存儲了客戶端請求協議的版本,比如"HTTP/1.1"
$request_body_file 變量中存儲了發給后端服務器的本地文件資源的名稱
$request_method 變量中存儲了客戶端的請求方式,比如"GET","POST"等
$request_filename 變量中存儲了當前請求的資源文件的路徑名
$request_uri 變量中存儲了當前請求的URI,並且攜帶請求參數,比如http://192.168.200.133/server?id=10&name=zhangsan中的"/server?id=10&name=zhangsan"

上述參數還可以在日志文件中使用,這個就要用到前面我們介紹的log_format指令

log_format main '$remote_addr - $request - $status-$request_uri  $http_user_agent';

access_log logs/access.log main;

if指令

該指令用來支持條件判斷,並根據條件判斷結果選擇不同的Nginx配置。

語法 if (condition){...}
默認值
位置 server、location

condition為判定條件,可以支持以下寫法:

  1. 變量名。如果變量名對應的值為空字符串或"0",if都判斷為false,其他條件為true。
if ($param){
	
}
  1. 使用"="和"!="比較變量和字符串是否相等,滿足條件為true,不滿足為false
if ($request_method = POST){
	return 405;
}

注意:此處和Java不太一樣的地方是字符串不需要添加引號,並且等號和不等號前后到需要加空格。

  1. 使用正則表達式對變量進行匹配,匹配成功返回true,否則返回false。變量與正則表達式之間使用"","*","!","!*"來連接。

    "~"代表匹配正則表達式過程中區分大小寫,

    "~*"代表匹配正則表達式過程中不區分大小寫

    "!"和"!*"剛好和上面取相反值,如果匹配上返回false,匹配不上返回true

if ($http_user_agent ~ MSIE){
	#$http_user_agent的值中是否包含MSIE字符串,如果包含返回true
}

注意:正則表達式字符串一般不需要加引號,但是如果字符串中包含"}"或者是";"等字符時,就需要把引號加上。

  1. 判斷請求的文件是否存在使用"-f"和"!-f",
if (-f $request_filename){
	#判斷請求的文件是否存在
}
if (!-f $request_filename){
	#判斷請求的文件是否不存在
}
  1. 判斷請求的目錄是否存在使用"-d"和"!-d"

  2. 判斷請求的目錄或者文件是否存在使用"-e"和"!-e"

  3. 判斷請求的文件是否可執行使用"-x"和"!-x"

break指令

該指令用於中斷當前相同作用域中的其他Nginx配置。與該指令處於同一作用域的Nginx配置中,位於它前面的指令配置生效,位於后面的指令配置無效。並且break還有另外一個功能就是終止當前的匹配並把當前的URI在本location進行重定向訪問處理。

語法 break;
默認值
位置 server、location、if

例子:

location /testbreak{
	default_type text/plain;
	set $username TOM;
	if ($args){
		Set $username JERRY;
        break;
		set $username ROSE;
	}
	add_header username $username;
	return 200 $username;
}

return指令

該指令用於完成對請求的處理,直接向客戶端返回。在return后的所有Nginx配置都是無效的。

語法 return code [text];
return code URL;
return URL;
默認值
位置 server、location、if

code:為返回給客戶端的HTTP狀態代理。可以返回的狀態代碼為0~999的任意HTTP狀態代理

text:為返回給客戶端的響應體內容,支持變量的使用

URL:為返回給客戶端的URL地址

location /testreturn {

	return 200 success;
}

location /testreturn {

	return https://www.baidu.com; // 302重定向到百度
}

location /testreturn {
	return 302 https://www.baidu.com;
}

location /testreturn {
	return 302 www.baidu.com;//不允許這么寫
}

rewrite指令

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

語法 rewrite regex replacement [flag];
默認值
位置 server、location、if

regex:用來匹配URI的正則表達式

replacement:匹配成功后,用於替換URI中被截取內容的字符串。如果該字符串是以"http://"或者"https://"開頭的,則不會繼續向下對URI進行其他處理,而是直接返回重寫后的URI給客戶端。

location rewrite {
	rewrite ^/rewrite/url\w*$ https://www.baidu.com;
	rewrite ^/rewrite/(test)\w*$ /$1;
	rewrite ^/rewrite/(demo)\w*$ /$1;
}
location /test{
	default_type text/plain;
	return 200 test_success;
}
location /demo{
	default_type text/plain;
	return 200 demo_success;
}

flag:用來設置rewrite對URI的處理行為,可選值有如下:

  • last:終止繼續在本location塊中處理接收到的URI,並將此處重寫的URI作為一個新的URI,使用各location塊進行處理。該標志將重寫后的URI重寫在server塊中執行,為重寫后的URI提供了轉入到其他location塊的機會。
location rewrite {
	rewrite ^/rewrite/(test)\w*$ /$1 last;
	rewrite ^/rewrite/(demo)\w*$ /$1 last;
}
location /test{
	default_type text/plain;
	return 200 test_success;
}
location /demo{
	default_type text/plain;
	return 200 demo_success;
}

訪問 http://192.168.200.133:8081/rewrite/testabc,能正確訪問

  • break:將此處重寫的URI作為一個新的URI,在本塊中繼續進行處理。該標志將重寫后的地址在當前的location塊中執行,不會將新的URI轉向其他的location塊。
location rewrite {
    #/test   /usr/local/nginx/html/test/index.html
	rewrite ^/rewrite/(test)\w*$ /$1 break;
	rewrite ^/rewrite/(demo)\w*$ /$1 break;
}
location /test{
	default_type text/plain;
	return 200 test_success;
}
location /demo{
	default_type text/plain;
	return 200 demo_success;
}

訪問 http://192.168.200.133:8081/rewrite/demoabc,頁面報404錯誤

  • redirect:將重寫后的URI返回給客戶端,狀態碼為302,指明是臨時重定向URI,主要用在replacement變量不是以"http://"或者"https://"開頭的情況。
location rewrite {
	rewrite ^/rewrite/(test)\w*$ /$1 redirect;
	rewrite ^/rewrite/(demo)\w*$ /$1 redirect;
}
location /test{
	default_type text/plain;
	return 200 test_success;
}
location /demo{
	default_type text/plain;
	return 200 demo_success;
}

訪問http://192.168.200.133:8081/rewrite/testabc請求會被臨時重定向,瀏覽器地址也會發生改變

  • permanent:將重寫后的URI返回給客戶端,狀態碼為301,指明是永久重定向URI,主要用在replacement變量不是以"http://"或者"https://"開頭的情況。
location rewrite {
	rewrite ^/rewrite/(test)\w*$ /$1 permanent;
	rewrite ^/rewrite/(demo)\w*$ /$1 permanent;
}
location /test{
	default_type text/plain;
	return 200 test_success;
}
location /demo{
	default_type text/plain;
	return 200 demo_success;
}

訪問http://192.168.200.133:8081/rewrite/testabc請求會被永久重定向,瀏覽器地址也會發生改變

rewrite_log指令

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

語法 rewrite_log on|off;
默認值 rewrite_log off;
位置 http、server、location、if

開啟后,URL重寫的相關日志將以notice級別輸出到error_log指令配置的日志文件匯總。

rewrite_log on;
error_log  logs/error.log notice;

Rewrite的案例

域名跳轉

》問題分析

先來看一個效果,如果我們想訪問京東網站,大家都知道我們可以輸入www.jd.com,但是同樣的我們也可以輸入www.360buy.com同樣也都能訪問到京東網站。這個其實是因為京東剛開始的時候域名就是www.360buy.com,后面由於各種原因把自己的域名換成了www.jd.com, 雖然說域名變量,但是對於以前只記住了www.360buy.com的用戶來說,我們如何把這部分用戶也遷移到我們新域名的訪問上來,針對於這個問題,我們就可以使用Nginx中Rewrite的域名跳轉來解決。

》環境准備

  • 准備三個域名:
vim /etc/hosts
127.0.0.1   www.itcast.cn
127.0.0.1   www.itheima.cn
127.0.0.1   www.itheima.com
  • 通過Nginx實現訪問www.itcast.cn
server {
	listen 80;
	server_name www.itcast.cn;
	location /{
		default_type text/html;
		return 200 '<h1>welcome to itcast</h1>';
	}
}

》通過Rewrite完成將www.ithema.com和www.itheima.cn的請求跳轉到www.itcast.com

server {
	listen 80;
	server_name www.itheima.com www.itheima.cn;
	rewrite ^/ http://www.itcast.cn;
}

問題描述:如何在域名跳轉的過程中攜帶請求的URI?

修改配置信息

server {
	listen 80;
	server_name www.itheima.com www.itheima.cn;
	rewrite ^(.*) http://www.itcast.cn$1;
}

域名鏡像

鏡像網站指定是將一個完全相同的網站分別放置到幾台服務器上,並分別使用獨立的URL進行訪問。其中一台服務器上的網站叫主站,其他的為鏡像網站。鏡像網站和主站沒有太大的區別,可以把鏡像網站理解為主站的一個備份節點。可以通過鏡像網站提供網站在不同地區的響應速度。鏡像網站可以平衡網站的流量負載、可以解決網絡寬帶限制、封鎖等。

而我們所說的域名鏡像和網站鏡像比較類似,上述案例中,將www.itheima.com和 www.itheima.cn都能跳轉到www.itcast.cn,那么www.itcast.cn我們就可以把它起名叫主域名,其他兩個就是我們所說的鏡像域名,當然如果我們不想把整個網站做鏡像,只想為其中某一個子目錄下的資源做鏡像,我們可以在location塊中配置rewrite功能,比如:

server {
    listen          80;
    server_name     www.itheima.cn www.itheima.com;
    location /user {
    	rewrite ^/user(.*)$ http://www.itcast.cn$1;
    }
    location /emp{
        default_type text/html;
        return 200 '<h1>emp_success</h1>';
    }
}

獨立域名

一個完整的項目包含多個模塊,比如購物網站有商品搜索模塊、商品詳情模塊和購物車模塊等,那么我們如何為每一個模塊設置獨立的域名。

需求:

http://search.itcast.com:81  訪問商品搜索模塊
http://item.itcast.com:82	  訪問商品詳情模塊
http://cart.itcast.com:83	  訪問商品購物車模塊
server{
	listen 81;
	server_name search.itcast.com;
	rewrite ^(.*) http://www.itcast.cn/search$1;
}
server{
	listen 82;
	server_name item.itcast.com;
	rewrite ^(.*) http://www.itcast.cn/item$1;
}
server{
	listen 83;
	server_name cart.itcast.com;
	rewrite ^(.*) http://www.itcast.cn/cart$1;
}

目錄自動添加"/"

問題描述

通過一個例子來演示下問題:

server {
	listen	8082;
	server_name localhost;
	location /heima {
		root html;
		index index.html;
	}
}

通過http://192.168.200.133:8082/heima和通過http://192.168.200.133:8082/heima/訪問的區別?

如果不加斜杠,Nginx服務器內部會自動做一個301的重定向,重定向的地址會有一個指令叫server_name_in_redirect on|off;來決定重定向的地址:

如果該指令為on
	重定向的地址為:  http://server_name:8082/目錄名/;
	http://localhost:8082/heima/
如果該指令為off
	重定向的地址為:  http://原URL中的域名:8082/目錄名/;
	http://192.168.200.133:8082/heima/

所以就拿剛才的地址來說,http://192.168.200.133:8082/heima如果不加斜杠,那么按照上述規則,如果指令server_name_in_redirect為on,則301重定向地址變為 http://localhost:8082/heima/,如果為off,則301重定向地址變為http://192.168.200.133:8082/heima/。后面這個是正常的,前面地址就有問題。

注意server_name_in_redirect指令在Nginx的0.8.48版本之前默認都是on,之后改成了off,所以現在我們這個版本不需要考慮這個問題,但是如果是0.8.48以前的版本並且server_name_in_redirect設置為on,我們如何通過rewrite來解決這個問題?

解決方案

我們可以使用rewrite功能為末尾沒有斜杠的URL自動添加一個斜杠

server {
	listen	80;
	server_name localhost;
	server_name_in_redirect on;
	location /heima {
		if (-d $request_filename){
			rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent;
		}
	}
}

合並目錄

搜索引擎優化(SEO)是一種利用搜索引擎的搜索規則來提高目的網站在有關搜索引擎內排名的方式。我們在創建自己的站點時,可以通過很多中方式來有效的提供搜索引擎優化的程度。其中有一項就包含URL的目錄層級一般不要超過三層,否則的話不利於搜索引擎的搜索也給客戶端的輸入帶來了負擔,但是將所有的文件放在一個目錄下又會導致文件資源管理混亂並且訪問文件的速度也會隨着文件增多而慢下來,這兩個問題是相互矛盾的,那么使用rewrite如何解決上述問題?

舉例,網站中有一個資源文件的訪問路徑時 /server/11/22/33/44/20.html,也就是說20.html存在於第5級目錄下,如果想要訪問該資源文件,客戶端的URL地址就要寫成 http://192.168.200.133/server/11/22/33/44/20.html,

server {
	listen 8083;
	server_name localhost;
	location /server{
		root html;
	}
}

但是這個是非常不利於SEO搜索引擎優化的,同時客戶端也不好記.使用rewrite我們可以進行如下配置:

server {
	listen 8083;
	server_name localhost;
	location /server{
		rewrite ^/server-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /server/$1/$2/$3/$4/$5.html last;
	}
}

這樣的花,客戶端只需要輸入http://www.web.name/server-11-22-33-44-20.html就可以訪問到20.html頁面了。這里也充分利用了rewrite指令支持正則表達式的特性。

防盜鏈

防盜鏈之前我們已經介紹過了相關的知識,在rewrite中的防盜鏈和之前將的原理其實都是一樣的,只不過通過rewrite可以將防盜鏈的功能進行完善下,當出現防盜鏈的情況,我們可以使用rewrite將請求轉發到自定義的一張圖片和頁面,給用戶比較好的提示信息。下面我們就通過根據文件類型實現防盜鏈的一個配置實例:

location /images {
    root html;
    valid_referers none blocked www.baidu.com;
    if ($invalid_referer){
        #return 403;
        rewrite ^/    /images/forbidden.png break;
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM