Nginx基礎知識點彙總1

1. 技術背景
水平擴展的可用性都需要靈活的負載均衡解決方案才能得以保障,NGINX
提供了多種協議的負載均衡解決方案如:HTTP、TCP 和 UDP 負載均衡。

2. HTTP實例

  1. 問題:將用戶請求分發到 2 臺以上 HTTP 服務器。
    解決方案
    使用 NGINX 的 HTTP 模塊,將請求分發到有 upstream 塊級指令代理的 HTTP
    服務器集羣,實現負載均衡:
upstream wlx{
	server 127.0.0.1:80 weight=1;
	server www.wlx.com:80 weight=2;
}
server {
	location / {
		proxy_pass http://wlx;
	}
}

3. HTTP 總結
HTTP 模塊的 upstream 用於設置被代理的 HTTP 服務器實現負載均衡。模塊
內定義一個目標服務器連接池,它可以是 UNIX 套接字、IP 地址、DNS 記錄
或它們的混合使用配置
;此外 upstream 還可以通過 weight 參數配置,如何
分發請求到應用服務器。
所有 HTTP 服務器在 upstream 塊級指令中由 server 指令配置完成。server
指令接收 UNIX 套接字、IP 地址或 FQDN(Fully Qualified Domain Name: 全限
定域名) 及一些可選參數。可選參數能夠精細化控制請求分發。它們包括用於負
載均衡算法的 weight 參數;判斷目標服務器是否可用,及如何判斷服務器可用
性的 max_fails 指令和 fail_timeout 指令。NGINX Plus 版本提供了許多其他
方便的參數,比如服務器的連接限制、高級DNS解析控制,以及在服務器啓動後
緩慢地連接到服務器的能力。
2. TCP實例
問題:將請求分發到 2 臺以上 TCP 服務器
解決方案
在 NGINX 的 stream 模塊內使用 upstream 塊級指令實現多臺 TCP 服務器負載
均衡:

stream {
	upstream mysql_read {
		server read1.example.com:3306 weight=5;
		server read2.example.com:3306;
		//backup 作爲備用數據庫服務器當負載請求分發失敗時會被啓用。
		server www.wlx.com:3306 backup;
	}
	server {
		listen 3306;
		proxy_pass mysql_read;
	}
}

3. TCP 總結
TCP 負載均衡在 stream 模塊中配置實現。stream 模塊類似於 http 模塊。
配置時需要在 server 塊中使用 listen 指令配置待監聽端口或 IP 加端口。
接着,需要明確配置目標服務,目標服務可以使代理服務或 upstream 指令
所配置的連接池。 TCP 負載均衡實現中的 upstream 指令配置和 HTTP 負載
均衡實現中的 upstream 指令配置相似。TCP 服務器在 server 指令中配置,
格式同樣爲 UNIX 套接字、IP地址或 FQDN(Fully Qualified Domain Name:
全限定域名);用於精細化控制的 weight 權重參數、最大連接數、DNS 解析
器、判斷服務是否可用和啓用爲備選服務的 backup 參數一樣能在 TCP 負載
均衡中使用

負載均衡算法(Load-Balancing Methods)
對於負載壓力不均勻的應用服務器或服務器連接池,**輪詢(round-robin)**負載均衡算法
無法滿足業務需求。使用 NGINX 提供的其它負載均衡算法,如:最少連接數(least connections)、最短響應時間(leaest time)、通用散列算法(generic hash)或 IP 散列算法(IP hash)

upstream backend {
	//最小連接數
	least_conn;
	server backend.example.com;
	server backend1.example.com;
}
upstream backend {
	//最短響應時間
	least_time;
	server backend.example.com;
	server backend1.example.com;
}
upstream backend {
	//通用散列算法
	has;
	server backend.example.com;
	server backend1.example.com;
}
upstream backend {
	/IP 散列
	ip_hash;
	server backend.example.com;
	server backend1.example.com;
}

實際落地
訪問應用時,可能由於網絡連接失敗,Web 服務器宕機或應用程序異常等原因導致
應用程序無法訪問。這時,代理或負載均衡器需要提供能夠智能檢測被代理或被負
載的 Web 服務是否無法訪問的能力,來確保不會請求分發到這些失效的服務器。
同時,客戶端會收到連接超時的響應,結束請求等待狀態。
通過代理服務器向被代理服務器發送健康檢測請求,來判斷被代理服務器是否失效,是
一種減輕被代理服務器壓力的有效方法。NGINX 服務器提供兩種不同的健康檢測案:
被動檢測和主動檢測,開源版的 NGINX 提供被動檢測功能, NGINX PLUS 提供主動檢
測功能。
主動檢測的實現原理是:
NGINX 代理服務向被代理服務器定時的發送連接請求,如果被代理服務器正常響應,則說明被代理服務器正常運行。
被動檢測的實現原理是:
NGINX 服務器通過檢測客戶端發送的請求及被代理(被負載均衡)服務器的響應結果進行
判斷被代理服務器是否失效。
被動檢測方案,可以有效降低被代理服務器的負載壓力;
主動檢測則能夠在客戶端發送請求之前,就能夠剔除掉失效服務器。

問題
你想對服務器進行有效檢測,但不止如何去檢測服務器健康狀況。
解決方案
使用一個簡單粗暴的檢測方案實現應用健康檢測。如,負載均衡器通過獲取被負載
服務器的響應狀態碼是否爲 200 判斷應用服務器進程是否正常。
結論
實際項目中,對被負載的提供核心功能的應用服務器進行健康檢測非常重要。
僅僅通過一種健康檢測方案,確保核心服務是否可用,通常並不完全可靠。
健康檢測應該通過網絡直接檢測被負載的應用服務器和應用本身是否運行正常,
來確保服務可用,這比僅使用負載均衡器來檢測服務是否可用要可靠。
一般,可以選擇一個功能來進行健康檢測,來確保整個服務是否可用。比如,
確認數據庫連接是否正常或應用是否能夠正常獲取它的資源。任何一個服務失效,
都可能引發蝴蝶效應導致整個服務不可用。

問題
需要檢測 TCP 服務器是否正常並從代理池中移除失效服務器。
解決方案
在 server 塊級指令中 使用 health_check 簡單指令,對被代理服務器進行
健康檢測:

stream {
	server {
		listen 3306;
		proxy_pass read_backend;
		health_check interval=10 passes=2 fails=3;
	}
}

上面的配置會對代理池中的服務器進行主動監測。如果被代理服務器未能正常
響應 NGINX 服務器的 3 個以上 TCP 連接請求,則被認爲是失效的服務。
之後,NGINX 服務器會每隔 10 秒進行一次健康檢測。
結論
在 NGINX PLUS 版本中同時提供被動檢測和主動檢測功能。被動檢測是通過加之於
客戶端與被代理服務器的請求響應檢測實現的。如果一個請求超時或者連接失敗,
被動檢測則認爲該被代理服務器失效。主動檢測則是通過明確的 NGINX 指令配置
來檢測服務器是否失效。主動檢測途徑可以是一個測試的連接,也可以是一個預期
的響應。

問題
需要主動檢測 HTTP 服務器健康狀態
解決方案
在 location 塊級指令中使用 health_check 指令檢測:

http {
server {
...
location / {
	proxy_pass http://backend;
	health_check interval=2s
	fails=2
	passes=5
	uri=/
	match=welcome;
	}
}
// status is 200, content type is "text/html",
// and body contains "Welcome to nginx!"
match welcome {
	status 200;
	header Content-Type = text/html;
	body ~ "Welcome to nginx!";
	}
}

通過向被代理服務器每隔 2 秒,發送一個到 ‘/’ URI 的請求來檢測
被代理服務器是否失效。被代理服務器連續接收 5 個請求,如果其中有 2 個
連續請求響應失敗,將被視作服務器失效。被代理服務器的健康響應格式
在 match 塊級指令中配置,規定響應狀態碼爲 200, 響應 Content-Type類型爲
‘text/html’,響應 body 爲 “Welcome to nginx!” 字符串的響應爲有效服務器。
結論
在 NGINX PLUS 版本中,除了通過響應狀態碼來判斷被代理服務器是否有效。
還能夠通過其它的一些響應指標來判斷是否有效。如:主動檢測的時間間隔
(頻率),主動請求的 URI 地址,健康檢測的請求次數及失敗次數和預期響應
結果等。在 health_check 指令中的 match 參數指向 match 塊級指令配置,
match 塊級指令配置定義了標準的響應,包括 status、header 和 body 指令,
他們都有各自的檢測標準。

介紹
通過對請求的響應結果進行緩存,能夠爲後續相同請求提供加速服務。對相同請求
響應內容進行內容緩存(Content Caching),相比每次請求都重新計算和查詢被代理
服務器,能有效降低被代理服務器負載。內容緩存能提升服務性能,降低服務器負
載壓力,同時意味着能夠使用更少的資源提供更快的服務。可伸縮的緩存服務從架構
層面來講,能夠顯著提升用戶體驗,因爲響應內容經過更少的轉發就能夠發送給用戶,
同時能提升服務器性能。

問題
需要定義響應內容的緩存路徑及緩存操作
解決方案
使用 proxy_cache_path 指令爲待緩存定義內容緩存區域的共享內存及緩存路徑

proxy_cache_path /var/nginx/cache
		keys\_zone=CACHE:60m
		levels=1:2
		inactive=3h
		max\_size=20g;
proxy_cache CACHE;

上面的配置中在 proxy_cache_path 指令中爲響應在文件系統中定義了緩存的存
儲目錄 /var/nginx/cache,並使用 keys_zone 參數創建名爲 CACHE 的擁有
60 M 的緩存內存空間;同時通過 levels 參數定義目錄解構級別,通過 inactive
參數指明如果相同請求的緩存在 3 小時內未被再次訪問則被釋放,並使用 max_size
定義了緩存最大可用存儲空間爲 20 G。
結論
要使用 NGINX 內容緩存,需要在配置中定義緩存目錄及緩存區域(zone)。
通過 proxy_cache_path 指令創建 NGINX 內容緩存,定義用於緩存信息的路
徑和用於存儲緩存的元數據(metadata)和運行時鍵名(active keys)的共享內存。
其它的可選參數,還提供緩存如何維護和訪問的控制,levels 參數定義如何
創建文件結構,定義子目錄的文件名長度,語法是以冒號分隔的值,支持最大
3 級。
NGINX 的所有緩存依賴於最終被計算成散列的 cache key,接着將結果以
cache key 作爲文件名,依據緩存級別創建緩存目錄。
inactive 參數用於控制最後一次使用緩存選項的時間,超過這個時間的緩存
會被釋放。緩存的大小則可以通過 max_size 參數進行配置。還有部分參數
作用於緩存加載進程中,功能是將 cache keys 從磁盤文件加載僅共享內存裏。
Caching Hash Keys 配置緩存哈希鍵名
問題
自定義如何緩存和查找緩存內容
解決方案
通過一條單獨的 proxy_cache_key 指令,以變量名的形式定義緩存命中和
丟棄的規則。

proxy_cache_key "$host$request_uri $cookie_user";

上例指令依據請求域名、請求 URI 和用戶 cookie 作爲緩存
鍵名,來構建 NGINX 的緩存頁面。這樣,就可以對動態頁面進行緩存,而
無需對每個用戶都進行緩存內容的生成處理。
結論
proxy_cache_key 默認設置是 “schemeschemeproxy_host $request_uri”。默認設置
適用於多數的使用場景。配置之中包括 scheme、HTTP 或 HTTPS、代理域名
(proxy_host)、請求的 URI 等變量。總之,它們能夠正確處理 NGINX 代理請求。
您可能會發現,對於每個應用程序,有許多其他的因素可以定義一個惟一的請求,
比如請求參數、頭文件、會話標識符等等,您需要創建自己的散列鍵。或許你
已經發現,對一個應用,還有其它的數據能夠確定一個唯一的請求,比如請求參數、
請求頭(headers)、會話標識(session identifiers) 等等,這些都可以用於
構建自己的散列鍵名。在構建時應基於應用程序的理解,創建選擇一個好的散列
鍵名,這一點非常重要。比較簡單的是爲靜態內容創建緩存鍵名,通常,可以直接
使用域名(hostname)和請求 URI 就可以了。而類似於儀表盤這類的,具有動態內
容的頁面,則需要充分了解用戶和應用之間的交互、以及用戶體驗之間的差異,來
構建緩存鍵名。如從安全的角度觸發,你可能不希望緩存將一個用戶的緩存數據展
示給另外的用戶。proxy_cache_key 令配置了用於緩存生成哈希值字符,此條指令
可以在 HTTP、server、location 塊級指令上下文中定義,實現對請求如何緩存的
靈活控制。
Cache Bypass 繞過緩存
問題
將一些內容不進行緩存
解決方案
將 proxy_cache_passby 指令,設置稱非空值或非 0。一種途徑是,在 location
塊級指令中設置一個值等於 1 的 proxy_cache_passby 指令

proxy_cache_bypass $http_cache_bypass;

配置告知 NGINX 服務器,如果一個 HTTP cache_passby 請求頭的值設置爲非
0(或非空),則不對該請求進行緩存處理
結論
挺多應用場景下都不應對請求進行緩存處理,對此,NGINX 提供 proxy_cache_passby
指令來應對這些場景。通過將指令值設置爲非空或非零,匹配的請求 URI 會直接發送給
被代理服務器,而不是從緩存中獲取。如何使用該指令,需要結合客戶端和應用的實際
使用。它既可以配製成如同一個請求變量一樣簡單,也可以配置成複雜的映射指令塊。
但最終目的都是繞過緩存。其中,一個重要的應用場景就是排除故障和調試應用。如果
在研發過程中一直使用緩存,或對特定用戶進行緩存,緩存會影響問題的復現。提供對指定
cookie、請求頭(headers)或請求參數等的緩存繞過能力,則是一個必要的功能。此外,
NGINX 服務器還能夠在 location 塊指令中將 proxy_cache 指令設置爲 off,完全禁用
緩存。

Cache Performance 緩存性能
問題
需要在客戶端提升服務性能
解決方案
使用客戶端緩存控制消息頭

location ~* .(css|js)$ {
expires 1y;
add\_header Cache-Control "public";
}

該 location 塊指令設置成功後,客戶端可以對 CSS 和 JS 文件進行緩存。expires 指令將所有緩存的有效期設置爲 1 年。add_header 指令將 HTTP 消息頭 Cache-Control 設置成 public 並加入響應中,表示所有的緩存服務器都可以緩存資源。如果將它的值
設置爲 private,則表示僅允許客戶端對資源進行緩存。
結論
緩存的性能和許多因素有關,其中磁盤讀寫速度是影響緩存性能的重要原因之一。
在 NGINX 配置指令中,還有很多能夠提升性能的指令。像上例中配置的,通過設置 Cache-Control 響應消息頭,客戶端會直接從本地讀取緩存,而不會將請求發送給服務器來提升性能。

用戶數據報協議(UDP) 在多種場景下運用,如 DNS、NTP 服務、IP語音(Voiceover IP)服務。NGINX 可以在 upstream 塊級指令中使用所有的負載均衡算法
實現 UDP 的負載均衡,本章將學習 UDP 負載均衡相關配置。
問題
需要在多臺 UDP 服務器間實現負載均衡
解決方案
NGINX stream 模塊實現 UDP 服務器的負載均衡,作爲 UDP 服務器的代理的 upstream 塊級指令被定義稱使用 UDP 協議:

stream {
	upstream ntp {
		server ntp1.example.com:123 weight=2;
		server ntp2.example.com:123;
	}
	server {
		listen 123 udp;
		proxy\_pass ntp;
	}
}

結論

或許有人會問 “既然有多條 A 記錄或 SRV 記錄的 DNS 域名解析,爲什麼我還需要使用 NGINX 的負載均衡功能呢?” 我們的理由是,NGINX 不僅提供了多種負載均衡算法,而且還能對 DNS 服務器本身進行負載均衡處理。UDP 協議構建了 DNS 解析、NTP 服務器、IP 語音服務等大量基礎服務。UDP 負載均衡在某些場景下運用不是特別廣泛,但在整個網絡世界則並非如此。UDP 負載均衡同 TCP 負載均衡一樣集成在 stream 模塊內,並且它們的使用方法也幾乎一樣。
二者的主要區別是,在 listen 指令中定義用於 UDP 協議的套接字及 udp 參數。此外,還有一些僅用於 UDP 協議的指令,像proxy_response 指令,proxy_response 指令告知 NGINX 服務器從被代理服務器接收多少預期響應,默認是無限制的,直到達到 proxy_timeout 設定值。

問題
檢測 upstream 指令中的 UDP 服務器是否健康。
解決方案
對 UDP 負載均衡配置進行健康檢測,確保只對正常運行的 UDP 服務器發送數據報文:

upstream ntp {
//配置採用被動檢測功能,將 max_fails 指令設置爲 3 次,fail_timeout設置爲 3 秒
	server ntp1.example.com:123 max\_fails=3 fail\_timeout=3s;
	server ntp2.example.com:123 max\_fails=3 fail\_timeout=3s;
}

結論
無論何種負載均衡,無論從用戶體驗角度,還是商業角度,健康檢測都至關重要。NGINX 同樣提供 UDP 負載均衡主動和被動檢測方案。被動檢測會監測連接失敗及超時請求作爲失效服務判斷。主動檢測會主動發送數據包值指定端口,通過配置的預期響應判斷服務是否有效。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章