NGINX 頻寬與連線數控制
對於負載量比較高的伺服器,可以設定每一位使用者可使用的資源上限,例如同時間最大連線數、連線頻率(每秒或每分鐘連線次數)以及下載速度。
同時間最大連線數
若要限制同時間最大連線數,首先要使用 limit_conn_zone
定義一個 key 與 zone 參數:
limit_conn_zone $binary_remote_addr zone=addr:10m;
這裡定義一個名為 addr
的 zone,空間大小是 10MB,worker 行程會使用這個 zone 所配置的共享記憶體空間來儲存 key 的計數值。這裡的我們使用 $binary_remote_addr 來作為判斷來源 IP 的依據(key),會使用這個二進位的變數來作為 key 是因為它跟一般的字串比起來,會比較省空間,如果 zone 所配置的共享記憶體空間用完了,那伺服器就會回傳 503(Service Temporarily Unavailable)的錯誤訊息。
接著再使用 limit_conn
指定一個 IP 同時間可以允許的最大連線數:
location /download/ { limit_conn addr 1; }
以上的設定只有對於來源 IP 做限制,如果要設定整台伺服器所有連線的上限值,可以這樣設定:
http { limit_conn_zone $server_name zone=server:10m; server { limit_conn server 1000; } }
這樣就可以把伺服器同時能夠接受的連線數上限設定為 1000
。
連線頻率
若要限制連線頻率,首先也是一樣要用 limit_req_zone
定義 key 與 zone 參數:
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
這裡除了定義 zone 的名稱與大小之外,還加上了一個 rate
指定連線頻率的上限,單位可以使用每秒的連線次數(r/s
)或是每分鐘的連線次數(r/m
),例如若要指定每分鐘不可超過 30 次連線,則設定為 30r/m
。
然後在需要限制連線頻率的地方加上 limit_req
的設定:
location /search/ { limit_req zone=one burst=5; }
這裡的 zone
就指定成剛剛上面定義的 zone 名稱,如果使用者所發出的連線頻率超過上限時,多出來的連線會先被放在伺服器的佇列中,等候一小段時間之後再處理,維持整體的連線頻率不會超過設定的上限,而 burst
參數是設定這個佇列的長度,如果連線數多到連佇列都放不下時,就會產生 503 的錯誤。
如果不想讓放在佇列中的請求延遲處理,可以加上 nodelay
:
limit_req zone=one burst=5 nodelay;
下載速度
若要限制每個連線的頻寬,可以使用 limit_rate
:
location /download/ { limit_rate 50k; }
在這樣的設定之下,每一個連線的下載速度最高不可超過每秒 50KB,但一個使用者可以同時開啟多條連線,如果需要限制連線數,可再加上 limit_conn
的限制條件:
location /download/ { limit_conn addr 1; limit_rate 50k; }
如果要讓使用者可以先下載一部份的資料,再進行連線頻寬的限制,可以使用 limit_rate_after
:
limit_rate_after 500k; limit_rate 20k;
這樣的設定可以讓使用者先下載 500KB 的資料之後,再進行限速,這通常會用在線上影音串流的網站,先讓使用者快速下載影音檔的表頭,然後再以正常的速度傳送串流資料,確認使用者是以串流的形式觀看,而不是直接下載。
以下是一個實際應用的範例,這個設定可讓一般的網頁同時可以接受 5 條連線(一般的瀏覽器通常最多使用 3 條),而在下載 /download/
之下的檔案時,一次只能下載一個檔案,1MB 以下的檔案不限速,超過 1MB 的檔案則限速每秒 50KB。
http { limit_conn_zone $binary_remote_address zone=addr:10m server { root /www/data; limit_conn addr 5; location / { } location /download/ { limit_conn addr 1; limit_rate_after 1m; limit_rate 50k; } } }
參考資料:NGINX
繼續閱讀: 12