相關文章:
《高可用服務設計之二:Rate limiting 限流與降級》
《nginx限制請求之一:(ngx_http_limit_conn_module)模塊》
《nginx限制請求之二:(ngx_http_limit_req_module)模塊》
《nginx限制請求之三:Nginx+Lua+Redis 對請求進行限制》
上一篇文章主要寫nginx限制連接數ngx_http_limit_conn_module 模塊的作用及使用方法,下面來寫ngx_http_limit_req_module模塊的作用及使用。
通過ngx_http_limit_req_module 模塊可以通過定義的鍵值來限制請求處理的頻率。特別的,可以限制來自單個IP地址的請求處理頻率。 限制的方法如同漏斗,每秒固定處理請求數,推遲過多請求。例如,單客戶端IP的每秒請求數。實現的原理是使用“漏桶”原理(限流算法之漏桶算法、令牌桶算法)。
該模塊提供了兩個配置參數,limit_req_zone 和 limit_req ,其中 limit_req_zone 只能配置在 http{} 段,而 limit_req 則可以配置於http{},server{},location{} 區段中。
第三方模塊編譯安裝參數:
一、limit_req_zone
語法:limit_req_zone $variable zone=name:size rate=rate;
配置段:http
該指令設置一塊共享內存限制域用來保存鍵值的狀態參數。特別是保存了當前超出請求的數量。鍵的值就是指定的變量(控制不被計算)。如:
注釋:
使用$binary_remote_addr變量,可以將每條狀態記錄的大小減少到64個字節,這樣1M的內存可以保存大約1萬6千個64字節的記錄
如果限制域的存儲空間耗盡了,對於后續所有請求,服務器都會返回503(Service Temporarily Unavailable)錯誤
速度可以設置為每秒處理請求數和每分鍾處理請求數,其值必須是整數,所以如果你需要每秒處理少於1個的請求,2秒處理一個請求,可以使用30r/m
二、limit_req
語法: limit_req zone=name burst=number [nodelay];
配置段:http,server,location
設置對應的共享內存限制域和允許被處理的最大請求數閥值。如果請求的頻率超過了限制域配置的值,請求處理會被延遲,所以所有的請求都是以定義的頻率被處理的。超過頻率限制的請求會被延遲,直到被延遲的請求數超過了定義的閥值,這時,這個請求會被終止,並返回503(Service Tempporarily Unavailable)錯誤,這個閥值的默認值為0,如:
限制頻率每秒不超過一個請求,同時允許超過頻率限制的請求數不多於100個;如果不希望超過的請求被延遲,可以用nodelay參數。
三、配置使用示例
limit_req_zone $binary_remote_addr zone=showjoy_req:20m rate=1r/s;
主要是用來定義變量,空間名稱,以及共享內存大小。
limit_req zone=showjoy_req burst=100 nodelay;
主要是用來使用前面定義的空間,定義請求頻率限制,使用nodelay則表示不希望超過的請求被延遲。
可能要對某些IP不做限制,需要使用到白名單。
模塊地址:https://yunpan.cn/cqSKP6BrJ2AeT 訪問密碼 4f50
關於limit_req和limit_conn的區別
1,首先,limit_req和limit_conn兩個模塊都是為了來限流的,但是兩者不在一個層面,為了搞清楚這個,必須先要弄清楚request和connection的區別,因為在很多情況下,我們把他們混淆了。
so, what is the difference between connection and request?
2, connection是連接,即常說的tcp連接,通過三次握手而建立的一個完整狀態機。建立一個連接,必須得要三次握手。
request是指請求,即http請求,(注意,tcp連接是有狀態的,而構建在tcp之上的http卻是無狀態的協議)。
通過打開一個網頁,然后通過wareshark可以看到,一個連接建立后(即三次握手后),在這個連接斷開之前(即四次揮手之前),會有很多的http request,這就是他們的區別:即一個連接的生命周期中,會存在一個或者多個請求,這是為了加快效率,避免每次請求都要三次握手建立連接,現在的HTTP/1.1協議都支持這種特性,叫做keepalive。
好了現在知道區別了。
3,那么在Nginx中,對於連接限制模塊:limit_conn_module來看:
limit_conn_zone $binanry_remote_addr zone=conn_zone:1m; locoation /limit.html { limit_conn conn_zone 1; }
這樣的配配置,表明以ip為key,來限制每個ip訪問lmit.html文件時候,最多只能有一個在線,否則其余的都要返回不可用。
這種情況就是一個靜止狀態的計數可以實現,而無關乎多長時間。
舉個例子,如果你的這個連接一直不釋放,即使你通過這一個連接發送出再多的request請求,只要我能夠應付,那么我就幫你處理。但是,如果你只需要處理2個請求,但是這兩個請求是分別用兩個連接同時發送過來的,那么,我就只能處理其中一個,另外一個就不行。這就是他的區別。
可以用ab命令來測試:
ab -n100 -c100 -k http://yoursit/limit.html
注意:ab命令的-n -c都是指的發送多少請求,即-n一共發送多少請求,-c同時發送多少請求,他並不關心需要多少連接來發送,默認情況下是每個請求都建立一個連接來發送。
上面這個命令,由於默認是一個連接發送一個請求,那么這將會同時建立100個連接,而這樣的話,就會導致限制超過(最多只能一個連接for一個ip)。99個請求都會失敗。
而如果你只開一個連接:
ab -n100 -c100 -k http://yousit/limt.html
這里的-k選秀就是表示keepalive,只開一個連接來發送這100個請求,即使是同時發送,那么server也不會認為你超過了,因為在一個時間你只是建立一個連接,這樣這100個請求都會干凈利落的處理完成。
3,再看limit_req_module
limit_req_zone $binary_remtoe_addr zone=req_zone:1m rate=1r/s; location /limit.html{ limit_conn zone=req_zone; }
注意和上面的區別:這里需要為共享內存配置一個速率rate
表明:對於每個ip來說,處理請求的速度不超過每秒1個請求。
可以看到這是個速度量(而上面的那個是數字量,速度和個數還是有直觀的區別的吧。。)
那么這時候 :
ab -n100 -c100 http://yoursit/limit.html
和
ab -n100 -c100 -k http://yousit/limt.html
的區別就不是那么明顯了,因為這總是同時發送出100個請求(不管是通過100個連接還是1個連接),只要你請求到底的速度超過每秒1個,那么我就會拒絕你。
附加:https://forum.linode.com/viewtopic.php?t=8064%3E