Nginx 限流 [7]

系統(tǒng)設計時一般會預估負載,當系統(tǒng)遭受惡意攻擊或正常突發(fā)流量等都可能導致系統(tǒng)被壓垮,而限流就是保護措施之一之景。

一、限流算法介紹

令牌桶算法

令牌桶限流

算法思想是:

  • 令牌以固定速率產(chǎn)生膏潮,并緩存到令牌桶中锻狗;
  • 令牌桶放滿時,多余的令牌被丟棄焕参;
  • 請求要消耗等比例的令牌才能被處理轻纪;
  • 令牌不夠時,請求被緩存叠纷。

漏桶算法

漏桶算法

算法思想是:

  • 水(請求)從上方倒入水桶刻帚,從水桶下方流出(被處理);
  • 來不及流出的水存在水桶中(緩沖)涩嚣,以固定速率流出崇众;
  • 水桶滿后水溢出(丟棄)。

這個算法的核心是:緩存請求航厚、勻速處理顷歌、多余的請求直接丟棄。

漏桶和令牌桶算法最明顯的區(qū)別在于是否允許突發(fā)流量(burst)的處理幔睬,漏桶算法能夠強行限制數(shù)據(jù)的實時傳輸(處理)速率衙吩,對突發(fā)流量不做額外處理;而令牌桶算法能夠在限制數(shù)據(jù)的平均傳輸速率的同時允許某種程度的突發(fā)傳輸溪窒。

二、Nginx 限流

Nginx 提供兩種限流方式冯勉,一是控制速率澈蚌,二是控制并發(fā)連接數(shù):

  • limit_req_zone 模塊用來限制單位時間內(nèi)的請求數(shù),即速率限制灼狰,采用的漏桶算法 "leaky bucket"宛瞄。
  • limit_req_conn 模塊用來限制同一時間連接數(shù),即并發(fā)限制。

控制速率

ngx_http_limit_req_module 模塊提供限制請求處理速率能力份汗,它能夠有效針對同一個 IP 反復請求服務器盈电,如洪水攻擊或者 DDos 攻擊。下面例子使用 nginx 的 limit_req_zone 和 limit_req 兩個指令杯活,限制單個IP的請求處理速率匆帚。

在 nginx.conf 的 http 域中添加限流配置:

# 格式:limit_req_zone key zone rate
http {
    limit_req_zone $binary_remote_addr zone=myRateLimit:10m rate=10r/s;
}

# 配置 server,使用 limit_req 指令應用限流旁钧。
server {
    location / {
        limit_req zone=myRateLimit;
        proxy_pass http://my_upstream;
    }
}
  • $binary_remote_addr:定義限流對象吸重,binary_remote_addr 是一種 key,表示基于 remote_addr(客戶端 IP) 來做限流歪今,binary_ 的目的是壓縮內(nèi)存占用量嚎幸。
  • zone:定義共享內(nèi)存區(qū)來存儲訪問信息, myRateLimit:10m 表示一個大小為10M寄猩,名字為myRateLimit的內(nèi)存區(qū)域嫉晶。1M 內(nèi)存能存儲16000個 IP 地址的訪問信息,10M 內(nèi)存可以存儲 16W個 IP地址訪問信息田篇。
  • rate:用于設置最大訪問速率替废,rate=10r/s 表示每秒最多處理10個請求。Nginx 實際上以毫秒為粒度來跟蹤請求信息斯辰,因此 10r/s 實際上是限制:每100毫秒處理一個請求舶担。這意味著,自上一個請求處理完后彬呻,若后續(xù)100毫秒內(nèi)又有請求到達衣陶,將拒絕處理該請求。
  • zone=myRateLimit 設置使用哪個配置區(qū)域來做限制闸氮,與 limit_req_zone 里的配置對應

處理突發(fā)流量

上面例子限制 10r/s剪况,正常流量稍微增大,請求就會被拒絕蒲跨,面對突發(fā)流量译断,可以結(jié)合 burst 參數(shù)使用來解決該問題。

server {
    location / {
        limit_req zone=myRateLimit burst=20;
        proxy_pass http://my_upstream;
    }
}

burst 譯為突發(fā)或悲、爆發(fā)孙咪,表示在超過設定的處理速率后能額外處理的請求數(shù)。當 rate=10r/s 時巡语,將1s拆成10份翎蹈,即每100ms可處理1個請求。此處男公,burst=20荤堪,若同時有20個請求到達,Nginx 會處理第一個請求,剩余19個請求將放入隊列澄阳,然后每隔100ms從隊列中獲取一個請求進行處理拥知。若請求數(shù)大于20,將拒絕處理多余的請求碎赢,直接返回 503

不過低剔,單獨使用 burst 參數(shù)并不實用。假設 burst=50揩抡,rate依然為10r/s户侥,排隊中的50個請求雖然每100ms會處理一個,但第50個請求卻需要等待 50 * 100ms即 5s峦嗤,這么長的處理時間自然難以接受蕊唐。因此,burst 往往結(jié)合 nodelay 一起使用烁设。

server {
    location / {
        limit_req zone=myRateLimit burst=20 nodelay;
        proxy_pass http://my_upstream;
    }
}

nodelay 針對的是 burst 參數(shù)替梨,burst=20 nodelay 表示這20個請求立馬處理,不能延遲装黑,相當于特事特辦副瀑。不過,即使這20個突發(fā)請求立馬處理結(jié)束恋谭,后續(xù)來了請求也不會立馬處理糠睡。burst=20 相當于緩存隊列中占了20個坑,即使請求被處理了疚颊,這20個位置這只能按 100ms 一個來釋放狈孔。
這就達到了速率穩(wěn)定,但突然流量也能正常處理的效果材义。

限制連接數(shù)

ngx_http_limit_conn_module 提供了限制連接數(shù)的能力均抽,利用 limit_conn_zone 和 limit_conn 兩個指令即可。下面是 Nginx 官方例子:

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;
}
  • limit_conn perip 10 作用的 key 是 $binary_remote_addr其掂,表示限制單個 IP 同時最多能持有10個連接油挥。
  • limit_conn perserver 100 作用的 key 是 $server_name,表示虛擬主機(server) 同時能處理并發(fā)連接的總數(shù)款熬。

需要注意的是:只有當 request header 被后端 server 處理后深寥,這個連接才進行計數(shù)。

設置白名單

限流主要針對外部訪問贤牛,內(nèi)網(wǎng)訪問相對安全翩迈,可以不做限流,通過設置白名單即可盔夜。利用 Nginx ngx_http_geo_module 和 ngx_http_map_module 兩個工具模塊即可搞定。

在 nginx.conf 的 http 部分中配置白名單:

geo $limit {
    default 1;       // key=default,  value=1  
    10.0.0.0/8 0;
    192.168.0.0/24 0;
    172.20.0.35 0;
    include conf/whiteip.conf;  // 支持白名單以 key:value的形式存儲在配置文件中
}

map $limit $limit_key {
    0 "";
    1 $binary_remote_addr; // value=1則返回 $binary_remote_addr,也就是IP喂链,否則返回空字符串  
}

limit_req_zone $limit_key zone=myRateLimit:10m rate=10r/s;
  • geo 定義了子網(wǎng)或 IP 與 0返十、1 的映射關系。上述配置中椭微,10.0.0.0/8 網(wǎng)段的 IP 映射到 0洞坑,而其他 IP 缺省映射到 1;
  • 來訪 IP 通過 geo 進行映射蝇率,映射結(jié)果是 0迟杂,表明該 IP 被列入白名單,經(jīng) map 轉(zhuǎn)換返回 "" 空字符串本慕;如果映射結(jié)果是1排拷,則返回 $binary_remote_addr,即客戶端實際 IP锅尘。
  • limit_req_zone 限流采用的 key 不再是 binary_remote_addr监氢,而是采用 $limit_key 動態(tài)獲取值。如果是白名單藤违,limit_req_zone 的限流 key 則為空字符串浪腐,將不會限流;若不是白名單顿乒,將會對客戶端真實 IP 進行限流议街。
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市璧榄,隨后出現(xiàn)的幾起案子特漩,更是在濱河造成了極大的恐慌,老刑警劉巖犹菱,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拾稳,死亡現(xiàn)場離奇詭異,居然都是意外死亡腊脱,警方通過查閱死者的電腦和手機访得,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來陕凹,“玉大人悍抑,你說我怎么就攤上這事《虐遥” “怎么了搜骡?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長佑女。 經(jīng)常有香客問我记靡,道長谈竿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任摸吠,我火速辦了婚禮空凸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘寸痢。我一直安慰自己呀洲,他們只是感情好,可當我...
    茶點故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布啼止。 她就那樣靜靜地躺著道逗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪献烦。 梳的紋絲不亂的頭發(fā)上滓窍,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天,我揣著相機與錄音仿荆,去河邊找鬼贰您。 笑死,一個胖子當著我的面吹牛拢操,可吹牛的內(nèi)容都是我干的锦亦。 我是一名探鬼主播,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼令境,長吁一口氣:“原來是場噩夢啊……” “哼杠园!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起舔庶,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤抛蚁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后惕橙,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瞧甩,經(jīng)...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年弥鹦,在試婚紗的時候發(fā)現(xiàn)自己被綠了肚逸。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,764評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡彬坏,死狀恐怖朦促,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情栓始,我是刑警寧澤务冕,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站幻赚,受9級特大地震影響禀忆,放射性物質(zhì)發(fā)生泄漏臊旭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一油湖、第九天 我趴在偏房一處隱蔽的房頂上張望巍扛。 院中可真熱鬧,春花似錦乏德、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至矢棚,卻和暖如春郑什,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蒲肋。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工蘑拯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人兜粘。 一個月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓申窘,卻偏偏與公主長得像,于是被迫代替她去往敵國和親孔轴。 傳聞我的和親對象是個殘疾皇子剃法,可洞房花燭夜當晚...
    茶點故事閱讀 44,665評論 2 354