Nginx現(xiàn)在已經(jīng)是最火的負(fù)載均衡之一,在流量陡增的互聯(lián)網(wǎng)面前,接口限流也是很有必要的,尤其是針對(duì)高并發(fā)的場(chǎng)景。Nginx的限流主要是兩種方式:限制訪問頻率和限制并發(fā)連接數(shù)。
一、限制訪問頻率(正常流量)
Nginx中我們使用 ngx_http_limit_req_module 模塊來限制請(qǐng)求的訪問頻率,基于漏桶算法原理實(shí)現(xiàn)。接下來我們使用 nginx limit_req_zone 和 limit_req 兩個(gè)指令,限制單個(gè)IP的請(qǐng)求處理速率。
語法:limit_req_zone key zone rate
- key :定義限流對(duì)象,binary_remote_addr 是一種key,表示基于 remote_addr(客戶端IP) 來做限流,binary_ 的目的是壓縮內(nèi)存占用量。
- zone:定義共享內(nèi)存區(qū)來存儲(chǔ)訪問信息, myRateLimit:10m 表示一個(gè)大小為10M,名字為myRateLimit的內(nèi)存區(qū)域。1M能存儲(chǔ)16000 IP地址的訪問信息,10M可以存儲(chǔ)16W IP地址訪問信息。
- rate 用于設(shè)置最大訪問速率,rate=10r/s 表示每秒最多處理10個(gè)請(qǐng)求。Nginx 實(shí)際上以毫秒為粒度來跟蹤請(qǐng)求信息,因此 10r/s 實(shí)際上是限制:每100毫秒處理一個(gè)請(qǐng)求。這意味著,自上一個(gè)請(qǐng)求處理完后,若后續(xù)100毫秒內(nèi)又有請(qǐng)求到達(dá),將拒絕處理該請(qǐng)求。
二、限制訪問頻率(突發(fā)流量)
按上面的配置在流量突然增大時(shí),超出的請(qǐng)求將被拒絕,無法處理突發(fā)流量,那么在處理突發(fā)流量的時(shí)候,該怎么處理呢?Nginx提供了 burst 參數(shù)來解決突發(fā)流量的問題,并結(jié)合 nodelay 參數(shù)一起使用。burst 譯為突發(fā)、爆發(fā),表示在超過設(shè)定的處理速率后能額外處理的請(qǐng)求數(shù)。
burst=20 nodelay 表示這20個(gè)請(qǐng)求立馬處理,不能延遲,相當(dāng)于特事特辦。不過,即使這20個(gè)突發(fā)請(qǐng)求立馬處理結(jié)束,后續(xù)來了請(qǐng)求也不會(huì)立馬處理。burst=20 相當(dāng)于緩存隊(duì)列中占了20個(gè)坑,即使請(qǐng)求被處理了,這20個(gè)位置這只能按 100ms一個(gè)來釋放。這就達(dá)到了速率穩(wěn)定,但突然流量也能正常處理的效果。
三、限制并發(fā)連接數(shù)
Nginx 的 ngx_http_limit_conn_module 模塊提供了對(duì)資源連接數(shù)進(jìn)行限制的功能,使用 limit_conn_zone 和 limit_conn 兩個(gè)指令就可以了。
- limit_conn perip 20:對(duì)應(yīng)的key是 $binary_remote_addr,表示限制單個(gè)IP同時(shí)最多能持有20個(gè)連接。
- limit_conn perserver 100:對(duì)應(yīng)的key是 $server_name,表示虛擬主機(jī)(server) 同時(shí)能處理并發(fā)連接的總數(shù)。注意,只有當(dāng) request header 被后端server處理后,這個(gè)連接才進(jìn)行計(jì)數(shù)。