目錄
引言
一、重寫功能
(一)if指令
1.判斷訪問使用的協議
2.判斷文件
(二)return指令
1.設置返回狀態碼
2.返回指定內容
3.指定URL
(三)set指令
1.手動輸入變量值
2.調用其它變量值為自定義變量
(四)break指令
(五)rewrite指令
1.permanent(永久重定向301)
2.redirect(臨時重定向302)
3.break
4.last
(六)防盜鏈
1.實現盜鏈
2.實現防盜鏈
二、反向代理
(一)實現代理
(二)針對一個URL進行代理
(三)動靜分離
(四)反向代理緩存
(五)反向代理客戶端 IP 透傳
1.單機代理透傳
2.多機代理透傳
(六)反向代理負載均衡
1.Nginx負載均衡策略
①.輪詢
②.加權輪詢
③hash
2.狀態參數
引言
在現代Web架構中,NGINX以其高性能、穩定性和靈活性而廣受青睞。本文將深入探討NGINX中的兩個核心功能:URL重寫和反向代理,以幫助您更好地理解和配置這些強大的特性。
一、重寫功能
在Nginx中,重寫(rewriting)功能主要用于改變請求的URI,以實現URL美化、路徑映射、SEO優化等目的。這主要通過 rewrite 指令來完成
Nginx服務器利用 ngx_http_rewrite_module 模塊解析和處理rewrite請求,此功能依靠 PCRE(perl compatible regular expression),因此編譯之前要安裝PCRE庫,rewrite是nginx服務器的重要功能之一,用于實現URL的重寫,URL的重寫是非常有用的功能,比如它可以在我們改變網站結構之后,不需要客戶端修改原來的書簽,也無需其他網站修改我們的鏈接,就可以設置為自動訪問,另外還可以在一定程度上提高網站的安全性。
例如在上文的https功能中,比如客戶去訪問京東或者淘寶,在不開啟重寫功能的清空下,如果直接輸入www.toabao.com去訪問網址,會通過http協議去訪問網址(http://www.taobao.com),它會提示這是一個不安全的網址,這樣會使訪問者擔心網址的安全性,從而放棄訪問。所以會開啟重寫功能,通過修改URL去使用https去訪問(https://www.taobao.com)
官方文檔: Module ngx_http_rewrite_module
(一)if指令
用于條件匹配判斷,并根據條件判斷結果選擇不同的Nginx配置,可以配置在server或location塊中進行配置,Nginx的if語法僅能使用if做單次判斷,不支持使用if else或者if elif這樣的多重判斷
官方文檔:Module ngx_http_rewrite_module
其基本用法為:
if (條件匹配) { ??
執行語句
}
使用正則表達式對變量進行匹配,匹配成功時if指令認為條件為true,否則認為false,變量與表達式之間使用以下符號鏈接
= | 比較變量和字符串是否相等,相等時if指令認為該條件為true,反之為false |
!= | 比較變量和字符串是否不相等,不相等時if指令認為條件為true,反之為false |
~ | 區分大小寫字符,可以通過正則表達式匹配,滿足匹配條件為真,不滿足匹配條件為假 |
!~ | 區分大小寫字符,判斷是否匹配,不滿足匹配條件為真,滿足匹配條件為假 |
~* | 不區分大小寫字符,可以通過正則表達式匹配,滿足匹配條件為真,不滿足匹配條件為假 |
!~* | 不區分大小字符,判斷是否匹配,滿足匹配條件為假,不滿足匹配條件為真 |
-f和!-f | 判斷請求的文件是否存在和是否不存在 |
-d和!-d | 判斷請求的目錄是否存在和是否不存在 |
-x和!-x | 判斷文件是否可執行和是否不可執行 |
-e和!-e | 判斷請求的文件或目錄是否存在和是否不存在(包括文件,目錄,軟鏈接) |
如果$變量的值為空字符串或0,則if指令認為該條件為false,其他條件為true。
nginx 1.0.1之前$變量的值如果以0開頭的任意字符串會返回false
1.判斷訪問使用的協議
使用其它客戶端進行訪問
2.判斷文件
判斷文件是否存在或不存在
$request_filename:訪問文件的絕對路徑
使用客戶端進行訪問
(二)return指令
return用于完成對請求的處理,并直接向客戶端返回響應狀態碼,比如:可以指定重定向URL(對于特殊重定向狀態碼,301/302等) 或者是指定提示文本內容(對于特殊狀態碼403/500等),處于此指令后的所有配置都將不被執行,return可以在server、if 和 location塊進行配置
官方文檔:Module ngx_http_rewrite_module
return code;?
#返回給客戶端指定的HTTP狀態碼return code [text];
#返回給客戶端的狀態碼及響應報文的實體內容,可以調用變量,其中text如果有空格,需要用單或雙引號return code url;
#返回給客戶端的URL地址
1.設置返回狀態碼
當訪問一個文件不存在時,正常的狀態碼為404,可以通過配置去修改返回的狀態碼
使用客戶端進行訪問
2.返回指定內容
return code [text];?
返回給客戶端的狀態碼及響應報文的實體內容,可以調用變量,其中text如果有空格,需要用單或雙引號
使用客戶端訪問
curl是文字版的瀏覽器可以看到指定的信息,但是圖形版瀏覽器不可以
需要使用default_type定義文本格式
3.指定URL
當用戶訪問到一個不存在的文件時,可以通過return指定狀態碼,并重定向到新指定的URL下
修改配置文件,并創建指定的URL
使用客戶端訪問不存在的文件時,就會跳轉到主頁面
可以看到,兩次訪問的結果并不一樣
第一次執行命令:curl ?192.168.83.40/xxx
這個命令沒有添加任何參數來處理服務器返回的HTTP重定向響應。在配置中設置了將 /xxx 路徑重定向到另一個URL。因此,curl 只顯示了服務器發送的302 Found響應的內容,而沒有自動跟隨重定向到新的URL。
第二次執行命令:curl ?192.168.83.40/xxx -L
這次執行時添加了 -L? 參數,它告訴 curl 在接收到服務器返回的重定向響應時自動跟隨并獲取最終的目標頁面內容。所以這次您看到了 "welcome to nginx",這是重定向目標頁面的實際內容。
也可以跳轉到其它網址
使用谷歌瀏覽器訪問不存在的頁面時,確實可以跳轉到指定的URL,但是狀態碼卻不是301
而是307
307:表示臨時重定向
因為瀏覽器會自行緩存,而訪問的是不存在的文件,并不會對該URL進行永久緩存
可以修改一下配置文件,通過訪問存在的頁面,跳轉到百度
因為URL是真實存在的文件,所以會永久緩存
(三)set指令
指令用于設置變量的值。這些變量可以在后續的配置塊或指令中使用
官方文檔:Module ngx_http_rewrite_module
1.手動輸入變量值
使用客戶端訪問不存在的文件時,就會輸出變量內容
2.調用其它變量值為自定義變量
也可以通過調用其它變量值,定義為自己設置的變量的值
使用客戶端訪問/ip
(四)break指令
用于中斷當前相同作用域(location)中的其他Nginx配置,與該指令處于同一作用域的Nginx配置中,位于它前面的配置生效,位于后面的 ngx_http_rewrite_module 模塊中指令(set、if等)就不再執行,Nginx服務器在根據配置處理請求的過程中遇到該指令的時候,回到上一層作用域繼續向下讀取配置,該指令可以在server塊和location、if塊中使用
官方文檔:Module ngx_http_rewrite_module
使用客戶端訪問測試
使用客戶端訪問時,只能看到break以上的 ngx_http_rewrite_module 模塊指令
(五)rewrite指令
通過正則表達式的匹配來改變URI,可以同時存在一個或多個指令,按照順序依次對URI進行匹配,rewrite主要是針對用戶請求的URL或者是URI做具體處理
官方文檔:Module ngx_http_rewrite_module
其語句塊寫法為:
rewrite?原始訪問URL? 實際訪問的URL? 標志[premanent(301)?redirect(302)?break、last]
正則匹配格式為:
. #匹配除換行符以外的任意字符
\w #匹配字母或數字或下劃線或漢字
\s #匹配任意的空白符
\d #匹配數字 [0-9]
\b #匹配單詞的開始或結束
^ #匹配字付串的開始
$ #匹配字符串的結束
* #匹配重復零次或更多次
+ #匹配重復一次或更多次
? #匹配重復零次或一次
(n) #匹配重復n次
{n,} #匹配重復n次或更多次
{n,m} #匹配重復n到m次
*? #匹配重復任意次,但盡可能少重復
+? #匹配重復1次或更多次,但盡可能少重復
?? #匹配重復0次或1次,但盡可能少重復
{n,m}? #匹配重復n到m次,但盡可能少重復
{n,}? #匹配重復n次以上,但盡可能少重復
\W ?#匹配任意不是字母,數字,下劃線,漢字的字符
\S #匹配任意不是空白符的字符
\D #匹配任意非數字的字符
\B #匹配不是單詞開頭或結束的位置
[^x] #匹配除了x以外的任意字符
[^kgc] #匹配除了kgc 這幾個字母以外的任意字符
注意:如果在同一級配置塊中存在多個rewrite規則,那么會自下而下逐個檢查;被某條件規則替換完成后,會重新一輪的替換檢查,隱含有循環機制,但不超過10次;如果超過,提示500響應碼,標志位用于控制此循環機制如果替換后的URL是以http://或https://開頭,則替換結果會直接以重定向返回給客戶端, 即永久重定向 301
rewrite 標志位?使用介紹
利用nginx的rewrite的指令,可以實現url的重新跳轉,rewrtie有四種不同的flag,分別是redirect(臨時重定向302)、permanent(永久重定向301)、break和last。其中前兩種是跳轉型的flag,后兩種是代理型
1.permanent(永久重定向301)
server {listen 80;server_name www.china.com;root /data/html;
location /computer {
rewrite ^/computer/(.*) /pc/$1 permanent;
#客戶端請求以 /computer 開頭并且后面跟隨任意內容(通過 (.*) 正則表達式捕獲)
#Nginx會使用rewrite指令將原始請求路徑重寫:/pc/$1(后向引用)也就是(.*)的內容
#permanent表示狀態碼為301
}
}
mkdir /data/html/pc
#創建指定URL
echo "welcome to txt" > /data/html/pc/txt
#創建數據文件,并添加內容
使用客戶端訪問時,訪問的絕對路徑為/data/html/computer/(.*)
這樣做的目的是永久性地將 /computer 下的所有資源映射到 /pc 相應的路徑下,以便進行URL結
構的調整或優化搜索引擎收錄等目的。
可以使用-vL查看跳轉的詳細信息
分析一下為什么需要加-L,查看不加-L的信息
可以看到,不加-L只得知狀態碼及新的URL,并沒有跟隨重定向跳轉,所以需要加上-L跟隨重定向
2.redirect(臨時重定向302)
臨時重定向,重寫完成后以臨時重定向方式直接返回重寫后生成的新URL給客戶端,由客戶端重新發起請求
redirect會返回狀態碼為302
permanent(永久重定向301)、redirect(臨時重定向302)的區別
永久重定向的,當nginx服務關閉后,它會從瀏覽器的緩存記錄中打開緩存的URL;而臨時重定向的關閉服務后無法進行訪問
當狀態碼為301時
curl是模擬瀏覽器,無法看到具體信息,可以使用谷歌瀏覽器的F12,查看信息。而谷歌瀏覽器因為文件類型限制原因,無法直接打開txt,需要將txt文件該命為以.txt結尾或.html結尾的等其它類型文件
mv? /data/html/pc/txt?? /data/html/pc/1.txt
此時關閉nginx服務,依然可以訪問到
如果狀態碼為302,只是臨時緩存,當服務關閉后就無法訪問
關閉服務后再次訪問就會訪問失敗
3.break
重寫完成后,停止對當前URL在當前location中后續的其它重寫操作,而后直接跳轉至重寫規則配置(如return、set)塊之后的其它配置;結束循環
使用客戶端訪問
當用戶訪問/data/html/computer/txt文件時,會正則匹配到第11行的內容,從而重定向URL到/data/html/pc/txt
4.last
重寫完成后,停止對當前URI在當前location中后續的其它重寫操作,而后對新的URL啟動新一輪重寫檢查,不建議在location中使用
適用于一個URL多次重寫,要注意避免出現超過十次以及URL重寫后返回錯誤的給用戶301
根據配置,在用戶訪問的時候,重定向后結束return 302;的指令,而后根據新的URL(/data/html/pc/txtx)匹配下面的location去執行新的location語句塊中的指令返回301狀態碼
當新的URL匹配不到任何語句塊時,則會直接訪問該URL
last與break的區別
last: 當使用 last 標志時,Nginx會停止當前location塊內剩余的所有 rewrite 規則,并重新開始尋找與新的URI匹配的location塊。這意味著Nginx會繼續檢查配置文件中的其他location塊以找到一個最適合處理已重寫請求的location。 如果沒有找到其他匹配的location,Nginx將使用最接近原始請求URI的location塊來處理請求。
break: 使用 break 標志時,Nginx同樣會停止當前location塊內剩余的所有 rewrite 規則,但是它不會重新查找新的location塊進行匹配。相反,它會在當前location塊內繼續執行后續的配置指令(如 proxy_pass、echo 等),或者直接返回響應給客戶端。
實戰:
使用重寫功能將HTTP協議轉換成HTTPS協議訪問
輸入http://192.168.83.40進行訪問
(六)防盜鏈
防盜鏈基于客戶端攜帶的referer實現,referer是記錄打開一個頁面之前記錄是從哪個頁面跳轉過來的標記信息,如果別人只鏈接了自己網站圖片或某個單獨的資源,而不是打開了網站的整個頁面,這就是盜鏈,referer就是之前的那個網站域名,正常的referer信息有以下幾種:
none
#請求報文首部沒有referer首部,比如用戶直接在瀏覽器輸入域名訪問web網站,就沒有referer信息。
blocked
#請求報文有referer首部,但無有效值,比如為空。
server_names
#referer首部中包含本主機名及即nginx 監聽的server_name。
arbitrary_string
#自定義指定字符串,但可使用*作通配符。示例: *.kgc.org www.kgc.*
regular expression
#被指定的正則表達式模式匹配到的字符串,要使用~開頭,例如:~.*\.kgc\.com
1.實現盜鏈
使用兩臺機器,兩個機器同時開啟http服務(nginx、httpd均可)
通過pc1去訪問pc2的圖片,且留在pc1的頁面
首先在pc2的主站點目錄上建一個文件
在pc1的web服務的主站點目錄上建立index.html文件,并輸入以下內容
這段HTML代碼定義了一個簡單的網頁結構,當在瀏覽器中打開時,會顯示以下內容:頁面標題(Heading 1)顯示文本 "this is 192.168.83.100",頁面中嵌入了一張圖片,其 src 屬性設置為 "http://192.168.83.40/nginx.jpg"。
這意味著瀏覽器將嘗試從 192.168.83.40 這個服務器上的 /nginx.jpg 路徑加載并顯示一張圖片
開啟pc1的http服務
使用真機去訪問pc1(192.168.83.100),就會顯示pc2(192.168.83.40)web服務主站點目錄下的nginx.jpg文件
也可以通過域名實現訪問
在192.168.83.100的web服務配置文件中添加域名解析
在pc2的配置文件中,添加server_name www.china.com;而后重新加載配置文件
在主機的C:\Windows\System32\drivers\etc/hosts文件中添加域名解析
解析pc1的主機
這個時候就可以使用域名進行訪問了
2.實現防盜鏈
在pc2的web服務配置文件中添加配置信息
location ~* \.(jpg|gif|swf|jpeg|bmp)$ {
#匹配所有以.jpg、.gif、.swf、.jpeg和.bmp結尾的URL路徑。
valid_referers none blocked *.china.com china.com;
#設置了有效的referer來源列表,允許以下幾種情況:
#none:表示沒有referer(直接訪問或通過鏈接工具打開)。
#blocked:表示referer被瀏覽器阻止了。
#*.china.com:表示所有以 .china.com 結尾的域名下的referer都是有效的。
#china.com:表示 china.com 主域名本身的referer也是有效的
if ( $invalid_referer ){
#如果請求的referer不在有效referer列表內,則 $invalid_referer 變量會被設置為真
return 403;
#返回HTTP狀態碼403
再去使用瀏覽器訪問時,就會拒絕訪問該文件
使用允許的域名可以訪問到
二、反向代理
反向代理:reverse proxy,指的是代理外網用戶的請求到內部的指定的服務器,并將數據返回給用戶的一種方式,這是用的比較多的一種方式
Nginx 除了可以在企業提供高性能的web服務之外,另外還可以將 nginx 本身不具備的請求通過某種預定義的協議轉發至其它服務器處理,不同的協議就是Nginx服務器與其他服務器進行通信的一種規范,主要在不同的場景使用以下模塊實現不同的功能
ngx_http_proxy_module: 這個模塊實現了HTTP反向代理功能。它允許Nginx接收客戶端的HTTP請求,并將請求轉發到上游服務器(如應用服務器),同時將上游服務器的響應返回給客戶端。通過此模塊,可以實現負載均衡、緩存等功能。
代理原理有兩種
同構代理:
- 當Nginx作為代理服務器時,如果其后端服務采用的是相同的技術棧、協議或者數據格式,我們可以稱這些后端為“同構”。例如,所有的后端都是基于HTTP/HTTPS協議提供RESTful API服務,并且返回的數據格式(如JSON)也一致。在這種情況下,Nginx只需要根據配置文件中的規則將請求轉發到合適的后端服務器即可,無需對請求或響應內容做過多的轉換處理。
異構代理:
- 而在異構環境中,Nginx后面的后端服務可能采用了不同的技術棧、協議或者數據格式。比如一部分是HTTP REST API,另一部分是PHP Python等服務,或者是不同版本的同一服務接口。此時,Nginx不僅需要正確地路由請求,還可能需要進行額外的協議轉換、負載均衡策略調整等復雜操作來適應不同后端的需求
ngx_http_upstream_module: 這個模塊與ngx_http_proxy_module緊密相關,用于定義一組后端服務器(upstream)作為代理的目標。它可以配置負載均衡算法,健康檢查等高級功能,以確保對后端服務器的高效和可靠訪問。
ngx_stream_proxy_module: 這個模塊提供了TCP/UDP協議層面上的代理服務,適用于非HTTP協議的應用場景,例如SMTP、IMAP、MySQL等基于TCP或UDP的服務。ngx_http_fastcgi_module: Nginx中的FastCGI代理模塊,用于處理PHP、Python等動態語言生成的內容。當接收到需要執行FastCGI程序的請求時,此模塊會將請求傳遞給FastCGI服務器(如PHP-FPM),并將執行結果返回給客戶端
ngx_http_uwsgi_module: 類似于ngx_http_fastcgi_module,這個模塊用于處理使用uWSGI協議的應用,通常用于Python(尤其是Django和Flask框架)應用程序的部署。該模塊將HTTP請求轉換為uWSGI協議格式并發送到支持uWSGI協議的后端應用服務器。
官方文檔: Module ngx_http_proxy_module
最簡單的理解方式就是客戶訪問web服務,通過代理服務器獲取web服務的數據信息
也可以設置多個代理服務器,主從服務,防止代理服務器掛了之后,導致整個服務崩壞
(一)實現代理
在配置文件中添加proxy_pass? 真實web服務地址;
代理服務器IP | 192.168.83.30 |
web服務器IP | 192.168.83.40 |
首先在代理服務器的配置文件中添加proxy_pass,開啟代理服務
在web服務器的根目錄下建立好數據文件
此時使用客戶端去訪問代理服務器就會訪問到web服務器的內容
也可以通過監聽端口和訪問端口進行設置,這樣,代理服務器既可以做代理服務器也可以提供web服務
配置代理服務器的配置文件
添加web服務的監聽端口
使用客戶端訪問不同的端口,會得到不同的結果
(二)針對一個URL進行代理
配置代理服務器文件,設置指定的URL
建立web服務器的數據文件
使用客戶端進行訪問不同的URL
(三)動靜分離
動靜分離是一種在Web服務器架構設計中常見的策略,它旨在提高系統性能、擴展性和穩定性。動靜分離主要是根據請求資源的特性將處理靜態內容和動態內容的任務分隔開。
動靜分離的概念:
動態內容(Dynamic Content):通常指那些需要服務器實時生成或處理的內容,如通過PHP、Java、Python等語言編寫的Web應用程序輸出的結果,或者數據庫查詢返回的數據。這些內容每次請求可能都會產生不同的結果。
靜態內容(Static Content):是指那些不會隨時間改變且可以被緩存的內容,例如HTML、CSS、JavaScript文件、圖片、視頻等。這些內容一旦生成,除非有更新,否則可以反復提供給多個用戶訪問而無需重新生成。
靜態資源服務器 | 192.168.83.40 |
動態資源服務器 | 192.168.83.100 |
代理服務器 | 192.168.83.30 |
在靜態資源服務器主站點目錄下建立靜態資源文件
在動態資源服務器主站點目錄下建立動態資源文件
修改代理服務器的配置文件
server {listen 80;server_name www.pla.com;root /data/;
#主站點目錄為/datalocation ~* /dynamic {
#此location語句塊匹配以/dynameic為起點的URLproxy_pass http://192.168.83.100;
#開啟代理服務,并指定如果訪問本機的/dynamic目錄下的所有文件,就是去訪問
#http://192.168.83.100/dynamic的相同URL的文件
}location ~* \.(jpg|html|txt|mp4)$ {
#匹配所有以.(jpg|html|txt|mp4)結尾的文件,用來區分靜態資源proxy_pass http://a192.168.83.40;
#開啟代理服務,如果匹配到以.(jpg|html|txt|mp4)結尾的文件的。
#就會跳轉到 http://192.168.83.40下相同URL的文件
}
}
使用客戶機訪問靜態資源
使用客戶機訪問動態資源
看起來與重寫功能區別不大,但是動靜分離可以做負載均衡,并有多個優點
提高響應速度:靜態資源可以從緩存或專用服務器快速獲取,降低延遲。
負載均衡優化:可以根據靜態和動態請求的特點分配不同類型的服務器資源,動態服務器可以專注于計算密集型任務,靜態服務器則側重于I/O性能。
擴展性增強:當流量增加時,可以根據需求獨立擴展靜態資源服務器和應用服務器的規模。
總結來說,動靜分離是通過合理的架構設計,使得系統能更高效地應對不同類型請求的一種優化手段,在現代Web服務中廣泛應用。
(四)反向代理緩存
反向代理緩存是Nginx作為高性能Web服務器和負載均衡器時提供的一項重要功能。在Nginx的反向代理場景下,它充當客戶端與后端應用服務器之間的中間層,可以緩存來自后端服務器的響應結果,并在后續相同的請求中直接提供已緩存的內容,從而減少對后端服務器的請求次數,提高整體系統的響應速度和可用性。同時,當后端服務器宕機后,在一定時間內依然可以訪問。
默認緩存功能關閉,通過添加proxy_cache語句開啟緩存功能
首先在代理服務器的主配置文件中添加圖片中的信息
如果在子配置文件中配置緩存功能,需要寫在定義的include子配置文件的上方,讀取配置從上往下,寫在下方先讀取子配置文件,該行指令可能不會生效
proxy_cache_path /data/nginx/proxy_cache
#指定緩存文件存儲的路徑為 /data/nginx/proxy_cache。levels=1:1:1
#定義了緩存目錄結構層級。這個參數表示將緩存文件按照三級目錄進行組織,每一級都是由一個字
#符組成(例如:/0/0/123)。這里的 1:1:1 表示每級目錄都只用一個字符來命名,可以根據實際
#需要調整級別和字符長度以適應大量緩存文件的組織需求。keys_zone=proxycache:20m
#創建了一個名為 proxycache 的共享內存區域,用來存儲緩存鍵值對以及一些元數據,分配給它
#的大小是 20MB。inactive=120s
#設置緩存項在120秒內未被訪問,則被視為過期并可能被清理掉。這意味著如果某個緩存內容在120
#秒內沒有被請求,那么它可能會從緩存中移除,釋放空間。max_size=1g
#設置緩存總容量的最大值為1GB。當緩存大小達到1GB時,Nginx會根據其內部策略(如LRU算法)自
#動刪除最不活躍或最早添加到緩存中的內容,以便為新內容騰出空間。
在子配置文件中添加信息
proxy_cache proxycache;
#在當前作用域內啟用緩存,并關聯到之前定義的名為 proxycache 的緩存區域。
#這意味著該server或location內的請求響應將根據策略被存儲在
#/data/nginx/proxy_cache 路徑下指定的緩存空間中。重啟服務后會自動生成該文件proxy_cache_key $request_uri;
#設置緩存鍵(key),這里使用了 $request_uri 變量作為緩存鍵。這意味著緩存
#會基于每個不同的請求URI進行區分,確保每個唯一的URI對應一個獨立的緩存項。proxy_cache_valid 200 302 301 10m;
#指定了對于HTTP狀態碼為200、302和301的響應,在成功獲取后可以緩存10分鐘。在此期
#間內,如果有相同的請求到達,Nginx將直接返回緩存中的內容,而不是再次向后端服務器發起請求。proxy_cache_valid any 5m;
#任何其他未明確指定狀態碼的響應(包括但不限于404、500等),其緩存有效時間為5分鐘。
#這意味著非200/301/302狀態碼的響應雖然也會被緩存,但其過期時間較短。
此時緩存目錄下是沒有任何文件的,需要訪問之后才會有緩存
當關閉192.168.83.40這個服務器之后,在一定時間內依然可以訪問到該信息
增加頭部信息
add_header? 自定義頭部名稱? 變量(信息)
add_header server_ip $server_addr;#這條指令會在響應頭中增加一個名為 "server_ip" 的字段,并將其值設置為當前服務器的IP地址
#($server_addr)。這有助于了解請求經過了哪些代理服務器或負載均衡器。add_header cache $upstream_cache_status;
#此指令添加了一個 "cache" 字段到響應頭中,其值由 $upstream_cache_status 變量提供。
#這個變量表示請求是否被緩存服務命中以及具體的緩存狀態,例如 "HIT"(命中)、"MISS"(未
#命中)等。這對于判斷反向代理緩存策略是否生效及其效果非常有幫助。add_header server_name $server_name;
#這個指令添加了一個名為server_name的字段,其值是當前服務器的主機名($server_name)。
#server_name;頭部與Nginx內部的ngx_http_proxy_module或ngx_http_fastcgi_module
#等模塊結合使用,用來標識內部請求加速或文件內部重定向等相關信息。
使用客戶端訪問并查看頭部信息
(五)反向代理客戶端 IP 透傳
在Nginx作為反向代理服務器時通常在接受到客戶端的請求后,會去訪問真實的web服務器,而此時web服務器的IP地址僅僅只有代理服務器的IP,并不能知道,訪問服務器資源的客戶端的IP地址
在上面的圖片中。作為web服務器,經過反向代理后,只能獲得代理服務器的IP(192.168.83.30),
并不能獲得客戶端IP(192.168.83.50)。
為了能夠正確地將客戶端的真實IP地址傳遞給后端應用服務器,需要配置Nginx將客戶端IP添加到請求頭中。這樣,即使經過了Nginx的代理,后端服務器也能識別出原始客戶端IP
1.單機代理透傳
只有一臺代理服務器的情況下進行透傳
代理服務器IP | 192.168.83.30 |
web服務器IP | 192.168.83.40 |
客戶端IP | 192.168.83.50 |
首先在代理服務器中添加:proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
指令設置了全局的請求頭轉發規則,將客戶端的真實IP地址(或者其他代理服務器傳遞過來的IP地址)通過 X-Forwarded-For 請求頭傳遞給后端服務器。$proxy_add_x_forwarded_for 變量會自動將客戶端IP添加到現有的 X-Forwarded-For 頭部中,如果沒有則創建一個新的頭部。
使用默認的日志格式,并打開將注釋刪除
使用客戶端訪問并查看日志web服務(192.168.83.40)的日志
可以看到,開頭的192.168.83.30是代理服務器訪問web服務器的$remote_addr,最后的192.168.83.50則是客戶端的真實IP
2.多機代理透傳
代理服務器可能會有多臺
代理服務器1:IP | 192.168.83.30 |
代理服務器2:IP | 192.168.83.100 |
web服務器IP | 192.168.83.40 |
客戶端IP | 192.168.83.50 |
首先來配置一號代理服務器
添加:proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
此時將客戶端的IP地址賦予x_forwarded_for
在配置二號代理服務器
此時再去訪問第一臺代理服務器,就會通過兩層代理到真實的web服務器
這是時候查看日志信息
(六)反向代理負載均衡
在上一個節中Nginx可以將客戶端的請求轉發至單臺后端服務器但是無法轉發至特定的一組的服務器,而且不能對后端服務器提供相應的服務器狀態監測,Nginx 可以基于ngx_http_upstream_module模塊提供服務器分組轉發、權重分配、狀態監測、調度算法等高級功能
反向代理負載均衡是一種將客戶端請求分發到一組后端服務器的技術,以分散負載、提高可用性和伸縮性。
由一臺代理服務器,指向兩臺真實的web服務器
代理服務器 | 192.168.83.30 |
web服務器1? | 192.168.83.40 |
web服務器2 | 192.168.83.100 |
在代理服務器上定義地址池,并開啟反向代理服務
官方文檔:Module ngx_http_upstream_module
upstream只能寫在http語句塊中
語法為:
upstream? 地址池name {
server web服務器IP地址;
server web服務器IP地址;
............
}
建立兩個web服務器的數據文件
使用客戶端進行訪問
可以看到,訪問時按地址池中的地址依次訪問,而后再次重新依次訪問,即訪問一次192.168.83.40.再訪問192.168.83.100,而后再訪問192.168.83.40,這樣依次訪問,這種方法也是upstream模塊默認的負載均衡默認策略。叫做輪詢
nginx服務有健康檢測機制,如果其中一臺服務器宕機,代理服務器并不會將請求發送給宕機的服務器,如果連接超時
1.Nginx負載均衡策略
Nginx負載均衡策略有以下幾種
①.輪詢
最基本的配置方法,上面的例子就是輪詢的方式。每個請求會按時間順序逐一分配到不同的后端服務器。
②.加權輪詢
按分配權重進行輪詢,使用weight進行分配
使用客戶端進行訪問,可以發現,訪問比例為3:1
如果設置成5:2,它的訪問比例為3:1加2:1
③hash
hash的主要作用是為了保持會話聯系。在負載均衡和反向代理的場景下,會話保持(Session Persistence)是一種確保客戶端與特定后端服務器之間維持持久連接的技術。當用戶在多個請求中需要共享同一會話狀態時,例如登錄狀態、購物車內容等,會話保持尤為重要。
hash分為三種
ip_hash
每個請求按訪問IP的hash結果分配,同一個IP客戶端固定訪問一個后端服務器。可以保證來自同一ip的請求被打到固定的機器上
在地址池中添加ip_hash或hash $remote_addr
這樣不論訪問多少次都會將訪問的客戶端的IP地址固定在一個服務器上
url_hash
按訪問url的hash結果來分配請求,使每個url定向到同一個后端服務器。一旦緩存住了資源,再次收到請求,就可以從緩存中讀取。
在地址池中添加hash $request_uri
使用客戶端進行訪問后,根據路徑分配后端服務器后,服務器會進行緩存,后續訪問會根據訪問路徑,調取緩存,訪問到同一個后端服務器
3.cookie hash
在Nginx中,實現基于Cookie的會話保持(Session Persistence)通常涉及到使用一個自定義的cookie或利用已存在的session cookie來決定將請求轉發到哪個后端服務器。這種技術有時被稱為“Cookie Hash”或“Cookie Stickiness”
使用客戶機訪問時加上不同的關鍵字
另外還有幾種策略
least_conn
把請求轉發給連接數較少的后端服務器。輪詢算法是把請求平均的轉發給各個后端,使它們的負載大致相同;但是,有些請求占用的時間很長,會導致其所在的后端負載較高。這種情況下,least_conn這種方式就可以達到更好的負載均衡效果
fair
此種算法可以依據頁面大小和加載時間長短智能地進行負載均衡,也就是根據后端服務器的響應時間來分配請求,響應時間短的優先分配
2.狀態參數
max_conns=number ?
#給當前后端server設置最大活動鏈接數,默認為0表示沒有限制
max_fails=number ?
#后端服務器的下線條件,當客戶端訪問時,對本次調度選中的后端服務器連續進行檢測
#多少次,如果都失敗就標記為不可用,默認為1次,當客戶端訪問時,才會利用TCP觸發對探
#測后端服務器健康性檢查,而非周期性的探測
fail_timeout=time
#后端服務器的上線條件,對已經檢測到處于不可用的后端服務器,每隔此時間間隔再次進行
#檢測是否恢復可用,如果發現可用,則將后端服務器參與調度,默認為10秒
backup ?
#設置為備份服務器,當所有后端服務器不可用時,才會啟用此備用服務器
down ? ?
#標記為down狀態
resolve
#當server定義的是主機名的時候,當A記錄(DNS解析)發生變化會自動應用新IP而不用重啟Nginx
這個時候去訪問代理服務器,只會將請求發送到192.168.83.40,當所有的服務器都宕機之后,,才會訪問到備用的服務器
再去訪問時就會訪問到備用機器