主要是分析兩種限流設置
Nginx 提供兩種限流方式,一是控制速率,二是控制併發鏈接數。
控制速率
正常限流node
ngx_http_limit_req_module 模塊提供限制請求處理速率能力,使用了漏桶算法(leaky bucket)。下面例子使用 nginx limit_req_zone 和 limit_req 兩個指令,限制單個IP的請求處理速率。nginx
在 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; } } key :定義限流對象,binary_remote_addr 是一種key,表示基於 remote_addr(客戶端IP) 來作限流,binary_ 的目的是壓縮內存佔用量。 zone:定義共享內存區來存儲訪問信息, myRateLimit:10m 表示一個大小爲10M,名字爲myRateLimit的內存區域。1M能存儲16000 IP地址的訪問信息,10M能夠存儲16W IP地址訪問信息。 rate 用於設置最大訪問速率,rate=10r/s 表示每秒最多處理10個請求。Nginx 實際上以毫秒爲粒度來跟蹤請求信息,所以 10r/s 其實是限制:每100毫秒處理一個請求。這意味着,自上一個請求處理完後,若後續100毫秒內又有請求到達,將拒絕處理該請求。
處理突發流量緩存
上面例子限制 10r/s,若是有時正常流量忽然增大,超出的請求將被拒絕,沒法處理突發流量,能夠結合 burst 參數使用來解決該問題。安全
server { location / { limit_req zone=myRateLimit burst=20; proxy_pass http://my_upstream; } }
burst 譯爲突發、爆發,表示在超過設定的處理速率後能額外處理的請求數。當 rate=10r/s 時,將1s拆成10份,即每100ms可處理1個請求。併發
此處,burst=20 ,若同時有21個請求到達,Nginx 會處理第一個請求,剩餘20個請求將放入隊列,而後每隔100ms從隊列中獲取一個請求進行處理。若請求數大於21,將拒絕處理多餘的請求,直接返回503.ide
不過,單獨使用 burst 參數並不實用。假設 burst=50 ,rate依然爲10r/s,排隊中的50個請求雖然每100ms會處理一個,但第50個請求卻須要等待 50 * 100ms即 5s,這麼長的處理時間天然難以接受。工具
所以,burst 每每結合 nodelay 一塊兒使用。code
server { location / { limit_req zone=myRateLimit burst=20 nodelay; proxy_pass http://my_upstream; } }
nodelay 針對的是 burst 參數,burst=20 nodelay 表示這20個請求立馬處理,不能延遲,至關於特事特辦。不過,即便這20個突發請求立馬處理結束,後續來了請求也不會立馬處理。burst=20 至關於緩存隊列中佔了20個坑,即便請求被處理了,這20個位置這隻能按 100ms一個來釋放。
這就達到了速率穩定,但忽然流量也能正常處理的效果。
限制鏈接數
ngx_http_limit_conn_module 提供了限制鏈接數的能力,利用 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) 同時能處理併發鏈接的總數。
須要注意的是:只有當 request header 被後端server處理後,這個鏈接才進行計數。
設置白名單
限流主要針對外部訪問,內網訪問相對安全,能夠不作限流,經過設置白名單便可。利用 Nginx ngx_http_geo_module 和 ngx_http_map_module 兩個工具模塊便可搞定。
在 nginx.conf 的 http 部分中配置白名單:
geo $limit { default 1; 10.0.0.0/8 0; 192.168.0.0/24 0; 172.20.0.35 0; } map $limit $limit_key { 0 ""; 1 $binary_remote_addr; } limit_req_zone $limit_key zone=myRateLimit:10m rate=10r/s;
geo 對於白名單(子網或IP均可以) 將返回0,其餘IP將返回1。
map 將 $limit 轉換爲 $limit_key,若是是 $limit 是0(白名單),則返回空字符串;若是是1,則返回客戶端實際IP。
limit_req_zone 限流的key再也不使用 $binary_remote_addr,而是 $limit_key 來動態獲取值。若是是白名單,limit_req_zone 的限流key則爲空字符串,將不會限流;若不是白名單,將會對客戶端真實IP進行限流。
拓展閱讀
除限流外,ngx_http_core_module 還提供了限制數據傳輸速度的能力(即常說的下載速度)。
例如:
location /flv/ { flv; limit_rate_after 20m; limit_rate 100k; }
這個限制是針對每一個請求的,表示客戶端下載前20M時不限速,後續限制100kb/s。
參考
https://chenyongjun.vip/articles/81