8.Nginx的請求限制( limit_conn_zone、 limit_conn、limit_req_zone、limit_req zone)

Nginx的請求限制

在配置nginx的過程中我們需要考慮受到攻擊或惡意請求的情況,比如單用戶惡意發起大量請求,這時Nginx的請求限制可以幫助我們對其進行限制。

連接頻率限制 : limit_conn_module

請求頻率限制 : limit_req_module

理解:連接頻率限制和請求頻率限制都可以實現Nginx的請求限制 , 但是他們的實現原理是不一樣的 , 區別就在于連接和請求上 , http協議的鏈接與請求 , http協議是建立在tcp協議之上的,要完成一次http的請求,先要進行tcp的3次握手建立http的連接 , 然后才進行http的request和response(請求和響應) , 現在http1.1以上的版本已經可以實現一次建立http的連接進行多次的http的request和response(請求和響應) ,最后客戶端和服務端不斷的來發送FIN包和ACK包來保持HTTP的連接 。

如果面對搶購和秒殺需求來限制 , 個人覺得連接頻率限制和請求頻率限制應該配合使用 , 使用連接頻率限制同一IP同時只能有3個連接, 再使用請求頻率限制對于同一ip的請求,限制平均速率為5個請求/秒 , 這樣是不是比單獨只使用一種限制要好很多?

比如只使用連接頻率限制 , 由于一次建立http的連接可以進行多次的請求和響應 , 我們無法精確的限制同一ip同時發起多少次的http請求 ;

比如只使用請求頻率限制 , 可以精確的限制同一ip1秒只能發起5次的http請求 , 假如同一ip1秒內發起了100000次請求 , 雖然限制了只有5次成功響應 , 但是其他的99995次的請求TCP握手建立http連接是不是會消耗服務器資源?

所以,個人覺得連接頻率限制和請求頻率限制應該配合使用!


HTTP協議的連接與請求

HTTP請求建立在一次TCP連接基礎上

一次TCP連接至少產生一次HTTP請求


連接限制

ngx_http_limit_conn_module模塊用于限制每個定義鍵的連接數,特別是來自單個IP地址的連接數。

配置示例

http {

????...

? ?#對單個ip、單個會話同時存在的連接數的限制。這里定義一個存儲區conn_zone,conn_zone的容量是1m,該存儲區針對于變量$binary_remote_add生效,這里是針對單個IP生效。該模塊只是一個定義,配置在http配置段,需要配合limit_conn指令使用才生效,?limit_conn one 1表示該location段使用conn_zone定義的?limit_conn_zone?,對單個IP限制同時存在一個連接。

? ? limit_conn_zone $binary_remote_addr zone=conn_zone:1m;

? ? server {

????????????location / {

? ? ? ? ? ? ? ? ? ? limit_conn conn_zone 1;

? ????????? }

}

做個演示:

未開啟連接限制時做個壓力測試 (不懂ab的可以看看https://www.cnblogs.com/TingJie/articles/4974885.html這個文章 , 很簡單明了)

ab -n 10000 -c 1000 http://192.168.58.100/index.html?

Complete requests:? ? ? 10000

Failed requests:? ? ? ? 78

這里模擬了10萬個請求 , 1000個并發 , 78個請求失敗,打開nginx的錯誤日志查看都是打開文件失敗的錯誤 ( open() "/usr/share/nginx/html/50x.html" failed (24: Too many open files))! 想象一下 , 如果我們是一個商城程序的API接口 , 正常情況下 , 同一個IP下10萬個請求1000個并發 , 算不算惡意攻擊?那么就需要做一下連接限制了噻 , 具體怎么限制根絕具體的邏輯去處理 , 我們這里簡單的限制一下(啟用配置示例的連接限制)再次做個壓力測試:

ab -n 10000 -c 1000 http://192.168.58.100/index.html?

Complete requests:? ? ? 100000

Failed requests:? ? ? ? 43616

開啟連接限制對單個IP限制同時只能存在一個連接,這里模擬了10萬個請求 , 1000個并發 , 43616個請求失敗,打開nginx的錯誤日志查看下錯誤全是連接限制的作用(limiting connections by zone "conn_zone") ,?我們知道"現在http1.1以上的版本已經可以實現一次建立http的連接進行多次的http的request和response(請求和響應)?" , 大家想想 , 如果我們需要做一個搶購和秒殺 , 是不是需要對單個搶購和秒殺限制連接單個IP同時只能存在一個或者多個連接的限制?不然人家寫個腳本程序運行在十臺八臺的機器上瘋狂的請求怎么辦?當然這只是一個比較簡單的應用場景 , 更多的還是需要自己思考與摸索.


請求限制

ngx_http_limit_req_module模塊用于限制請求的處理速率,特別是單一的IP地址的請求的處理速率。使用“漏桶”方法進行限制。

配置示例

http {

????...

? ?#$binary_remote_addr表示的是客戶端的地址,zone=req_zone:1m代表的是開辟了一個名為req_zone的1M的空間,1M的空間可以存儲多少個$binary_remote_addr這里不解釋了 , Nginx官網文檔介紹的相當清除 , 速率rate=1r/s代表的是每秒1個 , 所以這里定義的配置代表:對于同一ip的請求,限制平均速率為1個請求/秒。

? ? limit_req_zone $binary_remote_addr zone=req_zone:1m rate=1r/s;

????server {

? ? ? ? ? ? ...

? ? ????????location / {

? ? ? ????????????? root? /usr/share/nginx/html;

? ? ? ????????????? index? index.html index.htm;

? ? ? ? ? ? ? ? ? ? #請求限制 : 對于符合名為req_zone的limit_req_zone 配置(對于同一ip的請求,限制平均速率為1個請求/秒) ,?超過部分進行延遲處理,若超過3個請求/秒,丟棄超過部分。

????????????????????#limit_req zone=req_zone burst=3 nodelay;

? ? ? ? ? ? ? ? ? ? #請求限制 :?對于符合名為req_zone的limit_req_zone 配置?,超過部分進行延遲處理,若超過3個請求/秒,所有請求都被過度延遲,直到名為req_zone的limit_req_zone 配置設置的1M存儲區被占滿,如果存儲區耗盡,則刪除最近最少使用的狀態。即使在此之后無法創建新狀態,請求也會因錯誤而終止。

????????????????????#limit_req zone=req_zone burst=3;

????????????????????#請求限制 :?對于符合名為req_zone的limit_req_zone 配置(對于同一ip的請求,限制平均速率為1個請求/秒) 若超過1個請求/秒,所有請求都被過度延遲,直到名為req_zone的limit_req_zone 配置設置的1M存儲區被占滿,如果存儲區耗盡,則刪除最近最少使用的狀態。即使在此之后無法創建新狀態,請求也會因錯誤而終止。

????????????????????#limit_req zone=req_zone;

? ? ????????}

基本指令

limit_req_zone

語法:limit_req_zone?key zone=name:size rate=rate;

只能在http塊中使用

此指令用于聲明請求限制zonezone可以保存各種key的狀態,namezone的唯一標識,size代表zone的內存大小,rate指定速率限制。

參數詳解:

1.key

若客戶的請求匹配了key,則進入zone。可以是文本、變量,通常為Nginx變量。

$binary_remote_addr(客戶的ip),$uri(不帶參數的請求地址)$request_uri(帶參數的請求地址)$server_name(服務器名稱)

支持組合使用,使用空格隔開。

2.zone

使用zone=test,指定此zone的名字為test。

3.size

在zone=name后面緊跟:size,指定此zone的內存大小。如zone=name:10m,代表name的共享內存大小為10m。通常情況下,1m可以保存16000個狀態。

4.rate

使用rate=1r/s,限制平均1秒不超過1個請求。使用rate=1r/m,限制平均1分鐘不超過1個請求。

例子:

limit_req_zone $binary_remote_addr zone=one:10m rate=5r/s;

limit_req_zone $binary_remote_addr $uri zone=two:10m rate=1r/s;

同一ip不同請求地址,進入名為one的zone,限制速率為5請求/秒

同一ip同一請求地址,進入名為two的zone,限制速率為1請求/秒

limit_req?zone

語法:limit_req?zone=name [burst=number] [nodelay];

可在http, server, location塊中使用

此指令用于設置共享的內存zone和最大的突發請求大小。

若請求速率超過了limit_req_zone中指定的rate但小于limit_req中的burst,則進行延遲處理,若再超過burst,就可以通過設置nodelay對其進行丟棄處理。

參數詳解:

1.zone

使用zone=name指定使用名為namezone,這個zone之前使用limit_req_zone聲明過。

2.burst(可選)

burst用于指定最大突發請求數。許多場景下,單一地限制rate并不能滿足需求,設置burst,可以延遲處理超過rate限制的請求。

3.nodelay(可選)

如果設置了nodelay,在突發請求數大于burst時,會丟棄掉這部分請求。因為如果只是延遲處理,就像”漏斗“,一旦上面加得快(請求),下面漏的慢(處理速度),”漏斗“總會有溢出的時候。這時,丟棄掉溢出的部分就顯得很有意義了。

單客戶分為三種情況:

請求速率 < rate(1r/s),正常處理

rate(1r/s) < 請求速率 < burst(5r/s),大于rate部分延遲

burst(5r/s)? < 請求速率,大于burst部分丟棄(返回503服務暫時不可用)


做個演示:

未開啟請求限制時做個壓力測試 (不懂ab的可以看看https://www.cnblogs.com/TingJie/articles/4974885.html這個文章 , 很簡單明了)

ab -n 100000 -c 1000 http://192.168.58.100/index.html?

Complete requests:? ? ? 10000

Failed requests:? ? ? ? 0

這里模擬了10萬個請求 , 1000個并發 , 全部請求成功! 想想一下 , 如果我們是一個商城程序的API接口 , 正常情況下,同一個IP下10萬個請求算不算惡意攻擊?那么就需要做一下請求限制了噻 , 具體怎么限制根絕具體的邏輯去處理 , 我們這里簡單的限制一下:

同一ip請求,進入名為req_zone的zone,限制速率為20次請求/秒,

超過部分進行延遲處理,若超過10個請求/秒,丟棄超過部分。

http {

? ? limit_req_zone $binary_remote_addr zone=req_zone:1m rate=20r/s;

????server {

? ? ? ? ? ? ...

? ? ????????location / {

? ? ? ? ? ? ? ? ? ? ...

????????????????????#limit_req zone=req_zone burst=10 nodelay;

? ? ????????}

修改了配置之后平滑重啟一下nginx -s reload , 再次使用之前的參數做個壓力測試看看

同一IP發起了請求10萬次, nginx只接受處理了100次,是不是nginx的壓力一下子就小了

Complete requests: 100000

Failed requests:? ? ? ? 99900

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,836評論 6 540
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,275評論 3 428
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,904評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,633評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,368評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,736評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,740評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,919評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,481評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,235評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,427評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,968評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,656評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,055評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,348評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,160評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,380評論 2 379

推薦閱讀更多精彩內容