-
限流算法
-
令牌桶算法
令牌以固定的速率產生並放入令牌桶中,當令牌桶放滿后,多余的令牌會被拋棄;請求會消耗等比例的令牌。當令牌不夠用的時候,請求過來后沒有拿到令牌,這個請求就會被拒絕服務;
-
漏桶算法
請求好比是水流一樣。水從上面到桶中,從桶中以固定的速度流出。當上面的水流過大,桶中的水沒有來得及流出的時候,水就會暫時緩存到水桶中。水流過大,水桶存滿后就會溢出(溢出的部分相當於丟棄請求)
“漏桶算法”能夠強行限制數據的傳輸速率,而“令牌桶算法”在能夠限制數據的平均傳輸速率外,還允許某種程度的突發傳輸(比較極端的情況,當桶中的令牌存滿桶的時候,流量突增)。
-
-
限流配置
-
limit_req_zone
用來限制單位時間內的請求數,即速率限制,采用的漏桶算法 "leaky bucket"。
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; //$binary_remote_addr 表示通過remote_addr這個標識來做限制,“binary_”的目的是縮寫內存占用量,是限制同一客戶端ip地址。 //zone=one:10m表示生成一個大小為10M,名字為one的內存區域,用來存儲訪問的頻次信息。 //rate=1r/s表示允許相同標識的客戶端的訪問頻次,這里限制的是每秒1次,還可以有比如30r/m的。
limit_req zone=one burst=5 nodelay; //zone=one 設置使用哪個配置區域來做限制,與上面limit_req_zone 里的name對應。 //burst=5,設置一個大小為5的緩沖區當有大量請求(爆發)過來時,超過了訪問頻次限制的請求可以先放到這個緩沖區內。 //nodelay,如果設置,超過訪問頻次而且緩沖區也滿了的時候就會直接返回503,如果沒有設置,則所有請求會等待排隊。 //例: http { limit_req_zone $binary_remote_addr zone = one: 10 m rate = 1 r / s; server { location / search / { limit_req zone = one burst = 5 nodelay; } } } // 下面配置可以限制特定UA(比如搜索引擎)的訪問 http{ limit_req_zone $anti_spider zone = one: 10 m rate = 10 r / s; limit_req zone = one burst = 100 nodelay; if ($http_user_agent~ * "googlebot|bingbot|Feedfetcher-Google") { set $anti_spider $http_user_agent; } }
其他參數:
Syntax: limit_req_log_level info | notice | warn | error; Default: limit_req_log_level error; Context: http, server, location //設置你所希望的日志級別,當服務器因為頻率過高拒絕或者延遲處理請求時可以記下相應級別的日志。 延遲記錄的日志級別比拒絕的低一個級別;比如, 如果設置“limit_req_log_level notice”, 延遲的日志就是info級別。 Syntax: limit_req_status code; Default: limit_req_status 503; Context: http, server, location //設置拒絕請求的返回值 在400~599之間。
-
limit_req_conn
用來限制單個IP的請求數。並非所有的連接都被計數。只有在服務器處理了請求並且已經讀取了整個請求頭時,連接才被計數。
Syntax: limit_conn_zone key zone=name:size; Default: — Context: // 注: key的值為$binary_remote_addr 而不是 $ remote_addr;參考官方文檔:http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html#limit_conn_zone Syntax: limit_conn zone number; Default: — Context: http, server, location // 一次只允許每個IP地址一個連接 limit_conn_zone $binary_remote_addr zone=addr:10m; server { location /download/ { limit_conn addr 1; } } //限制每個客戶端IP連接到服務器的數量 為 10,同時限制連接到虛擬服務器的總數 為100 limit_conn_zone $binary_remote_addr zone=perip:10m; limit_conn_zone $server_name zone=perserver:10m; server { ... limit_conn perip 10; limit_conn perserver 100; }
其他配置:
// 當服務器限制連接數時,設置所需的日志記錄級別 Syntax: limit_conn_log_level info | notice | warn | error; Default: limit_conn_log_level error; Context: http, server, location // 設置狀態代碼以響應被拒絕的請求而返回 Syntax: limit_conn_status code; Default: limit_conn_status 503; Context: http, server, location
-
-
配置示例:
-
限制訪問速率
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s; server { location / { limit_req zone=mylimit; } }
此配置限制了 1s鍾可以處理請求兩次,500ms處理一次
-
burst緩存處理
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s; server { location / { limit_req zone=mylimit burst=4; } }
burst=4指每個key(此處是每個IP)最多允許4個突發請求的到來。如果單個IP在10ms內發送6個請求則會導致1個請求立即處理,4個請求被緩存,1個請求被拋棄。 有4個請求被放到burst隊列當中,工作進程每隔500ms(rate=2r/s)取一個請求進行處理,最后一個請求要排隊2s才會被處理;
注:burst的作用是讓多余的請求可以先放到隊列里,慢慢處理。如果不加nodelay參數,隊列里的請求不會立即處理,而是按照rate設置的速度,以毫秒級精確的速度慢慢處理。
-
nodelay降低排隊時間
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s; server { location / { limit_req zone=mylimit burst=4 nodelay; } }
nodelay參數允許請求在排隊的時候就立即被處理,也就是說只要請求能夠進入burst隊列,就會立即被后台worker處理,請注意,這意味着burst設置了nodelay時,系統瞬間的QPS可能會超過rate設置的閾值。nodelay參數要跟burst一起使用才有作用。
當單個ip在10ms中過來6個請求,成功請求率和上面一樣,成功5個,失敗1個。隊列中的請求同時具有了被處理的資格,可以當做 5個請求是同時開始被處理的,花費時間變短了。
注意:雖然設置burst和nodelay能夠降低突發請求的處理時間,但是長期來看並不會提高吞吐量的上限,長期吞吐量的上限是由rate決定的,因為nodelay只能保證burst的請求被立即處理,但Nginx會限制隊列元素釋放的速度,就像是限制了令牌桶中令牌產生的速度。
-
自定義返回值
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s; server { location / { limit_req zone=mylimit burst=4 nodelay; limit_req_status 598; } }
這樣設置,當請求因超過設置的閾值,返回的狀態碼就是 598
-
注:
-
參考文章:如何優雅地使用 Nginx 限流
-
了解文章:Nginx源代碼筆記-HTTP模塊-流控
-
整理不易,如需轉載 請注明出處 :https://www.cnblogs.com/zhuchenglin/p/12741299.html