分布式限流之Nginx層限流方式
寫在前面的話
- 高并發(fā)的三駕馬車:緩存、降級、限流,這里僅僅說限流
- 常用的限流算法有:計數(shù)器算法、固定窗口算法、滑動窗口算法、漏桶算法、令牌桶算法;每種算法的特點和優(yōu)缺點這里不展開,比較適用的限流算法基本都會選擇令牌桶,并且這里基于Spring Cloud Gateway Redis本身默認(rèn)就是基于令牌桶算法實現(xiàn)
- 限流按照類型分為:單機、分布式;
- 限流按照請求流量的路徑分為:nginx、gateway、微服務(wù)
- 如果僅僅使用于單機環(huán)境:谷歌guava的RateLimiter、(AtomicInteger、Semaphore)【AQS】都是可以選擇的; 但是在說到高并發(fā)基本已經(jīng)是分布式環(huán)境,此時的常用方案可以基于nginx的ngx_http_limit_req_module模塊、 gateway層基于 redis(底層使用lua腳本)、阿里的sentinel(需要單獨搭建服務(wù))等方案
當(dāng)前是限流的Nginx層處理,使用漏桶算法實現(xiàn),Nginx層限流允許基于客戶端ip進行控制,允許基于服務(wù)端與客戶端建立的鏈接數(shù)進行控制。
一定要清楚,當(dāng)前在這個位置:

1、基于ip數(shù)進行限制
更詳細官方文檔可以參考:https://www.nginx.com/blog/rate-limiting-nginx/
Ngixn層運行對請求的ip使用漏桶算法(leaky bucket algorithm)進行請求速率控制,速率限制配置有兩個主要指令,limit_req_zone和 limit_req
比如配置如下:
http {
limit_req_zone $binary_remote_addr zone=iplimit:10m rate=1r/s;
limit_req_zone $server_name zone=iplimit:10m rate=1r/s;
server {
server_name www.nginx-lyntest.com;
listen 80;
location ^~/my-api/ {
proxy_pass http://127.0.0.1:9999/;
limit_req zone=iplimit burst=20 nodelay;
limit_req_status 429; # 默認(rèn)返回 http 503狀態(tài)碼
limit_req_log_level warn; # 默認(rèn)為 error級別
}
}
}參數(shù)說明(當(dāng)定義并且配置了多個限流規(guī)則時,以最嚴(yán)格的為準(zhǔn)):
limit_req_zone指令:在http模塊進行設(shè)置;limit_conn_zone key鏈接限制的可選項,可以是下面的 $server_name 或 $binary_remote_addr
$binaty_remote_addrNGINX 變量以保存客戶端 IP 地址($remote_addr)的二進制;$server_nameNginx的變量,按照Server的server_name進行限流;zone=iplimit:10m指定一個變量名(iplimit)以保存上面指定的客戶端ip,當(dāng)前配置大小為10M,1M可以存儲大約 16,000 個 IP,這里的10M可以存儲16w個IP;rate=1r/s漏桶請求速率,控制在每秒1個請求;
limit_req指令:在location模塊指定上面http模塊約定的配置
zone=iplimit這里使用上面定義的zone區(qū)域以保存當(dāng)前l(fā)ocation的請求;burst=20設(shè)置一個大小20的槽的隊列,當(dāng)前超過漏桶速率數(shù)時將請求放入槽內(nèi),并且每 100 毫秒釋放 1 個插槽;官方解釋是以應(yīng)對流量突刺的情況。nodelay(或delay=8):當(dāng)前超過令牌桶速率時,并且上面配置的burst槽都滿的情況下,對請求處理。nodelay即不允許延遲馬上進行拒絕比較適用于需要高性能的接口??梢栽O(shè)置delay=一個指定的數(shù)值

limit_req_status:可以在【http、server、location】中使用,當(dāng)需要執(zhí)行拒絕時的http狀態(tài)碼,默認(rèn)為503,這里也可以指定為 429(Too Many Request)限流limit_req_log_level:可以在【http、server、location】中使用,限流的日志,默認(rèn)為error級別,這里可以指定為warm級別,官方的日志格式如
2015/06/13 04:20:00 [error] 120315#0: *32086 limiting requests, excess: 1.000 by
zone "mylimit", client: 192.168.1.2, server: nginx.com, request: "GET / HTTP/1.0",
host: "nginx.com"
正常請求沒有被限流的效果為:

默認(rèn)返回狀態(tài)狀態(tài)碼(limit_req_status默認(rèn)返回Http 503 狀態(tài)碼),效果為:

可以將limit_req_status調(diào)整為 Http 429狀態(tài)碼,效果為:

2、基于客戶端鏈接數(shù)進行控制
基于ngx_http_limit_conn_module,更詳細官方文檔可以參考:https://nginx.org/en/docs/http/ngx_http_limit_conn_module.html#limit_zone
http {
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;
server {
server_name www.nginx-lyntest.com;
listen 80;
location /my-api/ {
proxy_pass http://127.0.0.1:9999/;
# 每個server最多保持100個連接
limit_conn perserver 100;
# 每個ip最多保持1個連接
limit_conn perip 1;
limit_conn_log_level warm;
}
}
}limit_conn_zone指令,同樣在http模塊中進行設(shè)置;limit_conn_zone key鏈接限制的可選項,可以是下面的 $server_name 或 $binary_remote_addr
$binaty_remote_addrNGINX 變量以保存客戶端 IP 地址($remote_addr)的二進制;$server_nameNginx的變量,按照Server的server_name進行限流;zone= perip:10m指定一個變量名(perip)以保存上面指定的客戶端ip,當(dāng)前配置大小為10M,1M可以存儲大約 16,000 個 IP,這里的10M可以存儲16w個IP;zone=perserver:10m指定一個變量名(perserver)以保存根據(jù)server模塊名請求的統(tǒng)計進行限流;
limit_conn:配置上面設(shè)置的配置,并且設(shè)置鏈接個數(shù), 如上配置的是ip就限制ip的鏈接個數(shù),設(shè)置的是server模塊的名稱就限制其鏈接的個數(shù);
limit_conn_status:限制鏈接的返回Http 狀態(tài)碼,可以在【http、server、location】中使用,默認(rèn)返回值為 Http 503狀態(tài)碼,可以設(shè)置為 429 (Too Many Request)
limit_conn_log_level:可以在【http、server、location】中使用,連接日志可選項有:info| notice| warn| error,默認(rèn)級別為 error
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Nginx出現(xiàn)403 Forbidden的四種解決方案分享
這篇文章主要給大家分享了關(guān)于Nginx出現(xiàn)403 Forbidden的四種解決方案,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-09-09
Kubernetes之安裝nginx-controller作為統(tǒng)一網(wǎng)關(guān)方式
這篇文章主要介紹了Kubernetes之安裝nginx-controller作為統(tǒng)一網(wǎng)關(guān)方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07
淘寶Web服務(wù)器Tengine在CentOS下的安裝教程
這篇文章主要介紹了淘寶Web服務(wù)器Tengine在CentOS下的安裝教程,本文同時介紹了Tengine是什么,需要的朋友可以參考下2014-07-07
通過nginx反向代理來調(diào)試代碼的實現(xiàn)
這篇文章主要介紹了通過nginx反向代理來調(diào)試代碼的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01

