Nginx 作為網頁伺服器和反向代理伺服器,提供多種機制管理伺服器資源和提升效能。本文首先介紹如何使用 limit_conn 和 limit_req 模組限制連線數和請求速率,保護伺服器免受惡意攻擊和資源濫用。接著,文章探討 Nginx 的頻寬限制和快取機制,說明如何使用 limit_rate 限制客戶端下載速度,並詳細解釋如何設定快取區域、自定義快取鍵以及使用 proxy_cache 相關指令最佳化快取效能。最後,文章介紹了 Nginx Plus 提供的 API 和鍵值儲存功能,展示如何動態管理後端伺服器、執行快取清除和實作動態封鎖清單等進階應用。
連線與請求限制:保護伺服器資源
在管理伺服器資源時,限制連線數和請求速率是確保服務品質和防禦惡意攻擊的重要手段。Nginx 提供了強大的模組來實作這些功能。
限制連線數
當需要根據特定的鍵(如客戶端 IP 地址)限制連線數時,可以使用 limit_conn_zone 和 limit_conn 指令。
設定範例
http {
limit_conn_zone $binary_remote_addr zone=limitbyaddr:10m;
limit_conn_status 429;
# ...
server {
# ...
limit_conn limitbyaddr 40;
# ...
}
}
設定解說
limit_conn_zone指令:在http區塊中定義一個分享記憶體區域limitbyaddr,大小為 10 MB,用於儲存客戶端 IP 地址(二進位形式)的連線計數。limit_conn_status指令:設定當連線數超過限制時傳回的 HTTP 狀態碼為 429(Too Many Requests)。limit_conn指令:在server或location區塊中指定使用limitbyaddr區域,並設定最大連線數為 40。
重點分析
- 使用客戶端 IP 地址作為鍵可能會影響共用同一 IP 的多個使用者(如 NAT 後的使用者)。
- 可以使用其他變數(如 session cookie)來識別使用者,視具體情況而定。
limit_conn_status的預設值是 503,但使用 429 更適合表示客戶端錯誤。
請求速率限制
為了限制客戶端的請求速率,可以使用 limit_req_zone 和 limit_req 指令。
設定範例
http {
limit_req_zone $binary_remote_addr zone=limitbyaddr:10m rate=3r/s;
limit_req_status 429;
# ...
server {
# ...
limit_req zone=limitbyaddr;
# ...
}
}
設定解說
limit_req_zone指令:定義一個分享記憶體區域limitbyaddr,大小為 10 MB,限制速率為每秒 3 個請求。limit_req_status指令:設定超過速率限制時傳回的 HTTP 狀態碼為 429。limit_req指令:指定使用limitbyaddr區域進行請求速率限制。
重點分析
- 可以使用
burst和delay引數來調整速率限制策略,允許短暫的突發請求。 - 使用
nodelay引數可以讓客戶端立即消耗突發請求配額,但之後需要等待一段時間才能再次請求。 - 請求速率限制對於防禦暴力破解攻擊和資源濫用非常有效。
測試與驗證
無論是連線數限制還是請求速率限制,都需要在實際環境中進行測試和驗證。可以使用 limit_conn_dry_run 和 limit_req_dry_run 指令開啟乾跑模式,並透過日誌分析 $limit_conn_status 和 $limit_req_status 變數來調整限制策略。
NGINX 頻寬限制與快取最佳化
在現代網路架構中,伺服器資源的有效管理對於提供穩定且高效的服務至關重要。NGINX 作為一款高效能的網頁伺服器與反向代理伺服器,提供了多種機制來最佳化資源使用與提升使用者經驗。本文將探討 NGINX 的頻寬限制與快取機制,協助管理員實作更精細的流量控制與內容分發。
限制客戶端下載頻寬
在某些情況下,您可能需要限制客戶端的下載速度,以公平分配伺服器的上傳頻寬,或避免單一客戶端佔用過多資源。NGINX 提供了 limit_rate 和 limit_rate_after 指令來實作這一目標。
設定範例
location /download/ {
limit_rate_after 10m;
limit_rate 1m;
}
在上述設定中,對於 URI 以 /download/ 開頭的請求,NGINX 將在客戶端下載達到 10MB 後開始限制下載速度,最高下載速率被限制在每秒 1MB。這種設定確保了伺服器的頻寬能夠被多個客戶端公平分享。
詳細解析
limit_rate_after指令:定義了在傳輸多少資料後開始啟用速率限制。可以在http、server、location等多種上下文中使用。limit_rate指令:指定了速率限制的值,預設單位為每秒位元組數(bytes per second),也支援使用m表示每秒兆位元組或g表示每秒吉位元組。該指令同樣適用於多種上下文,並且可以透過變數$limit_rate進行動態設定。
快取機制最佳化
快取是提升內容分發效率的關鍵技術。NGINX 的快取功能可以將頻繁存取的內容儲存在本地,大幅減少對後端伺服器的請求壓力,並加快內容傳遞速度。
設定快取區域
要啟用 NGINX 的快取功能,首先需要定義快取儲存路徑和相關引數。
proxy_cache_path /var/nginx/cache
keys_zone=main_content:60m
levels=1:2
inactive=3h
max_size=20g
min_free=500m;
proxy_cache main_content;
上述範例中:
- 快取內容儲存在
/var/nginx/cache目錄下。 - 建立了一個名為
main_content的分享記憶體區域,大小為 60MB,用於儲存快取鍵和後設資料。 - 設定了目錄層級結構為
1:2,以避免單一目錄下檔案過多。 - 快取內容在最後一次存取後 3 小時內未被再次請求則被視為過期。
- 快取最大容量為 20GB,並設定了當可用磁碟空間低於 500MB 時開始清除快取。
快取鍵的自定義
透過 proxy_cache_key 指令,可以定義用於識別快取內容的鍵值,從而實作更精細的快取控制。
proxy_cache_key "$host$request_uri $cookie_user";
此範例中,快取鍵結合了請求的主機名、URI 和使用者 cookie,確保不同使用者即使請求相同的 URI 也能獲得各自的動態內容,而不會混淆快取結果。
結語
NGINX 提供了強大的頻寬控制和快取機制,可以幫助管理員最佳化伺服器資源分配,提升使用者經驗,並減少對後端伺服器的負載。透過合理組態 limit_rate、limit_rate_after、proxy_cache_path 和 proxy_cache_key 等指令,可以實作更高效、更靈活的內容分發策略。正確運用這些功能,不僅能夠提高服務品質,也能為使用者提供更穩定的服務體驗。
NGINX 快取最佳化
NGINX 的快取功能是提升網站效能的重要工具,正確組態快取機制能夠顯著減少伺服器負載並加快頁面載入速度。本篇文章將探討 NGINX 快取的相關設定與最佳實踐。
4.2 設定快取鍵值
在 NGINX 中,快取鍵值(cache key)的設定至關重要。預設的 proxy_cache_key 為 "$scheme$proxy_host$request_uri",涵蓋了協定(http 或 https)、代理主機和請求 URI,能夠滿足大多數使用場景。
proxy_cache_key "$scheme$proxy_host$request_uri";
內容解密:
- $scheme:代表使用的協定(http 或 https),確保不同協定的請求被快取在不同的位置。
- $proxy_host:指定請求被轉發到的主機名稱,有助於區分不同主機的快取內容。
- $request_uri:包含請求的 URI,能夠針對不同的 URI 進行快取。
選擇合適的快取鍵值需要深入理解應用程式的運作模式。對於靜態內容,快取鍵值可以使用主機名稱和 URI;而對於動態內容,可能需要考慮使用 session 識別符(如 cookies 或 JWT tokens)來建立獨特的快取鍵值。
4.3 快取鎖定機制
當多個請求同時嘗試存取同一資源時,快取鎖定機制能夠有效控制並發請求,確保只有一個請求能夠寫入快取。
proxy_cache_lock on;
proxy_cache_lock_age 10s;
proxy_cache_lock_timeout 3s;
內容解密:
- proxy_cache_lock on;:啟用快取鎖定機制,防止多個請求同時寫入快取。
- proxy_cache_lock_age 10s;:設定快取鎖定的最大存活時間為 10 秒,超過此時間後,NGINX 將允許另一個請求更新快取。
- proxy_cache_lock_timeout 3s;:設定請求等待快取鎖定的超時時間為 3 秒,超過此時間後,請求將直接轉發到後端伺服器。
4.4 使用過期快取
當後端伺服器不可用時,使用過期快取(stale cache)能夠提供基本的服務連續性。
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504 http_403 http_404 http_429;
內容解密:
- error:在後端伺服器無法選定的情況下,使用過期快取。
- timeout:在後端伺服器請求超時的情況下,使用過期快取。
- invalid_header:在後端伺服器傳回無效標頭的情況下,使用過期快取。
- updating:在快取正在更新的情況下,仍然使用過期快取,以減少對後端伺服器的負載。
4.5 略過快取
有時,需要略過快取直接存取後端伺服器。NGINX 提供了 proxy_cache_bypass 指令來實作此功能。
proxy_cache_bypass $http_cache_bypass;
內容解密:
- $http_cache_bypass:根據客戶端請求中的
Cache-Bypass標頭來決定是否略過快取。如果該標頭的值非零或非空,則略過快取。
4.6 使用 NGINX Plus 清除快取
NGINX Plus 提供了清除快取的功能,可以手動使特定的快取專案失效。
proxy_cache_purge <variable>;
內容解密:
- 需要設定一個變數來控制何時清除快取,該變數的值需要為非零或非空。
綜上所述,NGINX 的快取功能提供了多種設定選項,以滿足不同場景下的效能最佳化需求。正確組態這些選項,可以顯著提升網站的回應速度和可用性。
NGINX 快取管理與可程式化組態
NGINX 提供了多種強大的功能來管理和最佳化內容傳遞,其中包括快取管理和 API 組態。以下章節將詳細介紹如何使用 NGINX 進行快取清除、快取分片以及透過 API 進行動態組態。
快取清除
在 NGINX 中,快取清除是透過 proxy_cache_purge 指令實作的。這允許管理員透過特定的請求方法清除快取中的內容。以下是一個範例組態:
map $request_method $purge_method {
PURGE 1;
default 0;
}
server {
# ...
location / {
# ...
proxy_cache_purge $purge_method;
}
}
內容解密:
map $request_method $purge_method:根據請求方法對映到$purge_method變數。如果請求方法是PURGE,則$purge_method為 1,否則為 0。proxy_cache_purge $purge_method:當$purge_method為非零值時,清除對應的快取內容。
這項組態允許管理員使用 curl 命令清除特設定檔案的快取,例如:
$ curl -X PURGE http://www.example.com/main.js
快取分片
NGINX 的 slice 模組允許將大型檔案分割成小片段進行快取,從而提高快取效率。以下是一個範例組態:
proxy_cache_path /tmp/mycache keys_zone=mycache:10m;
server {
# ...
proxy_cache mycache;
slice 1m;
proxy_cache_key $host$uri$is_args$args$slice_range;
proxy_set_header Range $slice_range;
proxy_http_version 1.1;
proxy_cache_valid 200 206 1h;
location / {
proxy_pass http://origin:80;
}
}
內容解密:
slice 1m:將回應分割成 1MB 的片段。proxy_cache_key $host$uri$is_args$args$slice_range:根據主機名、URI、查詢引數和分片範圍設定快取鍵。proxy_set_header Range $slice_range:在請求中設定Range標頭,以取得特定的分片。proxy_http_version 1.1:升級 HTTP 版本以支援位元組範圍請求。
這種組態特別適用於 HTML5 影片等需要位元組範圍請求的場景,能夠提高 NGINX 快取和提供內容的效率。
NGINX Plus API
NGINX Plus 提供了一個強大的 API,用於動態組態和管理伺服器。以下是一個範例組態:
upstream backend {
zone http_backend 64k;
}
server {
# ...
location /api {
api write=on;
# Directives limiting access to the API
# See chapter 7
}
location = /dashboard.html {
root /usr/share/nginx/html;
}
}
內容解密:
upstream backend { zone http_backend 64k; }:定義一個分享記憶體區域,用於儲存 upstream 伺服器的狀態。api write=on:啟用 NGINX Plus API,並允許寫入操作。location = /dashboard.html:提供 NGINX Plus 控制檯的存取入口。
透過這個 API,可以動態地新增或移除 upstream 伺服器,例如:
$ curl -X POST -d '{"server":"172.17.0.3"}' \
'http://nginx.local/api/9/http/upstreams/backend/servers/'
NGINX Plus API 動態流量管理與鍵值儲存應用
NGINX Plus 提供了一套 RESTful API,允許動態管理後端伺服器和流量控制。本文將介紹如何使用 NGINX Plus API 動態管理後端伺服器,以及如何利用鍵值儲存進行動態流量管理決策。
動態管理後端伺服器
NGINX Plus API 允許應用程式動態地新增或移除後端伺服器。以下是一個範例,展示如何使用 curl 命令新增一個後端伺服器到 backend 上游組態:
$ curl -X POST -d '{"server":"172.17.0.3:80"}' 'http://nginx.local/api/9/http/upstreams/backend/servers/'
{
"id":0,
"server":"172.17.0.3:80",
"weight":1,
"max_conns":0,
"max_fails":1,
"fail_timeout":"10s",
"slow_start":"0s",
"route":"",
"backup":false,
"down":false
}
內容解密:
- 使用
curl傳送 POST 請求到 NGINX Plus API,新增一個後端伺服器。 - 請求主體是一個 JSON 物件,包含要新增的伺服器資訊。
- 回應是一個 JSON 物件,包含新伺服器的組態資訊,包括自動生成的
id。
列出上游伺服器
可以使用 NGINX Plus API 列出上游池中的所有伺服器:
$ curl 'http://nginx.local/api/9/http/upstreams/backend/servers/'
[
{
"id":0,
"server":"172.17.0.3:80",
"weight":1,
"max_conns":0,
"max_fails":1,
"fail_timeout":"10s",
"slow_start":"0s",
"route":"",
"backup":false,
"down":false
}
]
內容解密:
- 傳送 GET 請求到 NGINX Plus API,列出
backend上游池中的所有伺服器。 - 回應是一個 JSON 陣列,包含每個伺服器的組態資訊。
排空連線與移除伺服器
在移除一個伺服器之前,可以使用 NGINX Plus API 排空其連線:
$ curl -X PATCH -d '{"drain":true}' 'http://nginx.local/api/9/http/upstreams/backend/servers/0'
{
"id":0,
"server":"172.17.0.3:80",
"weight":1,
"max_conns":0,
"max_fails":1,
"fail_timeout":"10s",
"slow_start":"0s",
"route":"",
"backup":false,
"down":false,
"drain":true
}
內容解密:
- 使用 PATCH 請求指示 NGINX Plus 對指定伺服器進行連線排空。
- 請求主體是一個 JSON 物件,包含
"drain":true以啟動連線排空。
確認連線排空完成後,可以移除該伺服器:
$ curl -X DELETE 'http://nginx.local/api/9/http/keyvals/blocklist'
[]
內容解密:
- 使用 DELETE 請求移除指定的伺服器。
- 回應是一個空的 JSON 陣列,表示上游池中剩餘的伺服器。
鍵值儲存與動態流量管理
NGINX Plus 的鍵值儲存功能允許應用程式注入資訊以進行動態流量管理決策。以下是一個使用鍵值儲存實作動態封鎖清單的範例:
keyval_zone zone=blocklist:1M;
keyval $remote_addr $blocked zone=blocklist;
server {
# ...
location / {
if ($blocked) {
return 403 'Forbidden';
}
return 200 'OK';
}
}
server {
# ...
location /api {
api write=on;
}
}
鍵值儲存架構圖示
@startuml
skinparam backgroundColor #FEFEFE
skinparam sequenceArrowThickness 2
title Nginx 連線請求限制與快取最佳化
actor "客戶端" as client
participant "API Gateway" as gateway
participant "認證服務" as auth
participant "業務服務" as service
database "資料庫" as db
queue "訊息佇列" as mq
client -> gateway : HTTP 請求
gateway -> auth : 驗證 Token
auth --> gateway : 認證結果
alt 認證成功
gateway -> service : 轉發請求
service -> db : 查詢/更新資料
db --> service : 回傳結果
service -> mq : 發送事件
service --> gateway : 回應資料
gateway --> client : HTTP 200 OK
else 認證失敗
gateway --> client : HTTP 401 Unauthorized
end
@enduml
此圖示說明瞭 NGINX Plus 如何根據鍵值儲存區中的值進行流量控制決策。
新增與更新鍵值
可以使用 NGINX Plus API 新增或更新鍵值:
$ curl -X POST -d '{"127.0.0.1":"1"}' 'http://127.0.0.1/api/9/http/keyvals/blocklist'
內容解密:
- 傳送 POST 請求到 NGINX Plus API,新增或更新鍵值儲存區中的鍵值對。
- 請求主體是一個 JSON 物件,包含要新增或更新的鍵值對。
刪除鍵值:
$ curl -X PATCH -d '{"127.0.0.1":null}' 'http://127.0.0.1/api/9/http/keyvals/blocklist'
內容解密:
- 使用 PATCH 請求並設定值為
null以刪除指定的鍵。