長這么大才讀懂高并發(fā)核心編程,限流原理與實戰(zhàn),Nginx漏桶限流
Nginx漏桶限流詳解
使用Nginx可通過配置的方式完成接入層的限流,其ngx_http_limit_req_module模塊所提供的limit_req_zone和limit_req兩個指令使用漏桶算法進行限流。其中,limit_req_zone指令用于定義一個限流的具體規(guī)則(或者計數(shù)內(nèi)存區(qū)),limit_req指令應(yīng)用前者定義的規(guī)則完成限流動作。

假定要配置Nginx虛擬主機的限流規(guī)則為單IP限制為每秒1次請求,整個應(yīng)用限制為每秒10次請求,具體的配置如下:
#第一條規(guī)則名稱為perip,每個相同客戶端IP的請求限速在6次/分鐘(1次/10秒)
limit_req_zone $binary_remote_addr zone=perip:10m rate=6r/m;
#第二條限流規(guī)則名稱為preserver,同一虛擬主機的請求限速在10次/秒
limit_req_zone $server_name zone=perserver:1m rate=10r/s;
server {
listen 8081 ;
server_name localhost;
default_type 'text/html';
charset utf-8;
limit_req zone=perip;
limit_req zone=perserver;
location /nginx/ratelimit/demo {
echo "-uri= $uri -remote_addr= $remote_addr"
"-server_name= $server_name" ;
}
}上面的配置通過limit_req_zone指令定義了兩條限流規(guī)則:第一條規(guī)則名稱為perip,將來自每個相同客戶端IP的請求限速在6次/分鐘(1次/10秒);第二條限流規(guī)則名稱為preserver,用于將同一虛擬主機的請求限速在10次/秒。
以上配置位于練習(xí)工程LuaDemoProject的src/conf/nginxratelimit.conf文件中,在使之生效前需要在openresty-start.sh腳本中換上該配置文件,然后重啟Nginx。接下來開始驗證上面的限流配置。在瀏覽器中輸入如下測試地址:
http://nginx.server:8081/nginx/ratelimit/demo10秒內(nèi)連續(xù)刷新,第1次的輸出如圖9-9所示。

圖9-9 Nginx限流后10秒內(nèi)連續(xù)刷新的第1次輸出
10秒內(nèi)連續(xù)刷新,第1次之后的輸出如圖9-10所示。

圖9-10 Nginx限流后10秒內(nèi)連續(xù)刷新第1次之后的輸出
接下來詳細介紹Nginx的limit_req_zone和limit_req兩個指令。
limit_req_zone用于定義一個限流的具體規(guī)則,limit_req應(yīng)用前者所定義的規(guī)則。limit_req_zone指令的格式如下:
語法:limit_req_zone key zone=name:size rate=rate [sync];
上下文:http配置塊limit_req_zone指令的key部分是一個表達式,其運行時的值將作為流量計數(shù)的關(guān)鍵字,key表達式包含變量、文本和它們的組合。在上面的配置實例中,$binary_remote_addr、$server_name為兩個Nginx變量,$binary_remote_addr為客戶端IP地址的二進制值,$server_name為虛擬機主機名稱。在限流規(guī)則應(yīng)用之后,它們的值將作為限流關(guān)鍵字key值,同一個key值會在限流的共享內(nèi)存區(qū)域保存一份請求計數(shù),而limit_req_zone限流指令所配置的速度限制只會對同一個key值發(fā)生作用。
limit_req_zone指令的zone屬性用于定義存儲相同key值的請求計數(shù)的共享內(nèi)存區(qū)域,格式為name:size,name表示共享內(nèi)存區(qū)域的名稱(或者說限流規(guī)則的名稱),size為共享內(nèi)存區(qū)域的大小。上面的配置實例中,perip:10m表示一個名字為perip、大小為10MB的內(nèi)存區(qū)域。
1MB大約能存儲16 000個IP地址,10MB大約可以存儲16萬個IP地址,也就是可以對16萬個客戶端進行并發(fā)限速,當(dāng)共享內(nèi)存區(qū)域耗盡時,Nginx會使用LRU算法淘汰最長時間未使用的key值。
limit_req_zone指令的rate屬性用于設(shè)置最大訪問速率,rate=10r/s表示一個key值每秒最多能計數(shù)的訪問數(shù)為10個(10個請求/秒),rate=6r/m表示一個key值每分鐘最多能計數(shù)的訪問數(shù)為6個(1個請求/10秒)。由于Nginx的漏桶限流的時間計算是基于毫秒的,當(dāng)設(shè)置的速度為6r/m時,轉(zhuǎn)換一下就是10秒內(nèi)單個IP只允許通過1個請求,從第11秒開始才允許通過第二個請求。
limit_req_zone指令只是定義限流的規(guī)則和共享內(nèi)存區(qū)域,規(guī)則要生效的話,還得靠limit_req限流指令完成。
limit_req指令的格式如下:
語法:limit_req zone=name [burst=number] [nodelay | delay=number];上下文:http配置塊,server配置塊,location配置塊limit_req指令的zone區(qū)域?qū)傩灾付ǖ南蘖鞴蚕韮?nèi)存區(qū)域(或者說限流的規(guī)則)與限流規(guī)則指令limit_req_zone中的name對應(yīng)。
limit_req指令的burst突發(fā)屬性表示可以處理的突發(fā)請求數(shù)。
limit_req指令的第二個參數(shù)burst是爆發(fā)數(shù)量的意思,此參數(shù)設(shè)置一個大小為number的爆發(fā)緩沖區(qū),當(dāng)有大量請求過來時,超過了限流頻率的請求可以先放到爆發(fā)緩沖區(qū)內(nèi),直到爆發(fā)緩沖區(qū)滿后才拒絕。
limit_req指令的burst參數(shù)的配置使得Nginx限流具備一定的突發(fā)流量的緩沖能力(有點像令牌桶)。但是burst的作用僅僅是讓爆發(fā)的請求先放到隊列里,然后慢慢處理,其處理的速度是由limit_req_zone規(guī)則指令配置的速度(比如1個請求/10秒),在速率低的情況下,其緩沖效果其實并不太理想。如果想迅速處理爆發(fā)的請求,那么可以再加上nodelay參數(shù),隊列中的請求會立即處理,而不再按照rate設(shè)置的速度(平均間隔)慢慢處理。
本文給大家講解的內(nèi)容是高并發(fā)核心編程,限流原理與實戰(zhàn),Nginx漏桶限流詳解
下篇文章給大家講解的是高并發(fā)核心編程,限流原理與實戰(zhàn),實戰(zhàn):分布式令牌桶限流;
覺得文章不錯的朋友可以轉(zhuǎn)發(fā)此文關(guān)注小編;
感謝大家的支持!
本文就是愿天堂沒有BUG給大家分享的內(nèi)容,大家有收獲的話可以分享下,想學(xué)習(xí)更多的話可以到微信公眾號里找我,我等你哦。
