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

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; # 默認返回 http 503狀態(tài)碼
limit_req_log_level warn; # 默認為 error級別
}
}
}參數(shù)說明(當定義并且配置了多個限流規(guī)則時,以最嚴格的為準):
limit_req_zone指令:在http模塊進行設置;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,當前配置大小為10M,1M可以存儲大約 16,000 個 IP,這里的10M可以存儲16w個IP;rate=1r/s漏桶請求速率,控制在每秒1個請求;
limit_req指令:在location模塊指定上面http模塊約定的配置
zone=iplimit這里使用上面定義的zone區(qū)域以保存當前l(fā)ocation的請求;burst=20設置一個大小20的槽的隊列,當前超過漏桶速率數(shù)時將請求放入槽內(nèi),并且每 100 毫秒釋放 1 個插槽;官方解釋是以應對流量突刺的情況。nodelay(或delay=8):當前超過令牌桶速率時,并且上面配置的burst槽都滿的情況下,對請求處理。nodelay即不允許延遲馬上進行拒絕比較適用于需要高性能的接口??梢栽O置delay=一個指定的數(shù)值

limit_req_status:可以在【http、server、location】中使用,當需要執(zhí)行拒絕時的http狀態(tài)碼,默認為503,這里也可以指定為 429(Too Many Request)限流limit_req_log_level:可以在【http、server、location】中使用,限流的日志,默認為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"
正常請求沒有被限流的效果為:

默認返回狀態(tài)狀態(tài)碼(limit_req_status默認返回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模塊中進行設置;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,當前配置大小為10M,1M可以存儲大約 16,000 個 IP,這里的10M可以存儲16w個IP;zone=perserver:10m指定一個變量名(perserver)以保存根據(jù)server模塊名請求的統(tǒng)計進行限流;
limit_conn:配置上面設置的配置,并且設置鏈接個數(shù), 如上配置的是ip就限制ip的鏈接個數(shù),設置的是server模塊的名稱就限制其鏈接的個數(shù);
limit_conn_status:限制鏈接的返回Http 狀態(tài)碼,可以在【http、server、location】中使用,默認返回值為 Http 503狀態(tài)碼,可以設置為 429 (Too Many Request)
limit_conn_log_level:可以在【http、server、location】中使用,連接日志可選項有:info| notice| warn| error,默認級別為 error
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Nginx出現(xiàn)403 Forbidden的四種解決方案分享
這篇文章主要給大家分享了關于Nginx出現(xiàn)403 Forbidden的四種解決方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-09-09
Kubernetes之安裝nginx-controller作為統(tǒng)一網(wǎng)關方式
這篇文章主要介紹了Kubernetes之安裝nginx-controller作為統(tǒng)一網(wǎng)關方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07
通過nginx反向代理來調(diào)試代碼的實現(xiàn)
這篇文章主要介紹了通過nginx反向代理來調(diào)試代碼的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-01-01

