nginx?流控使用的項(xiàng)目實(shí)踐
正常限制訪問頻率(正常流量)
流量限制”配置兩個主要的指令,limit_req_zone和limit_req,如下所示:
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s; server { location /login/ { limit_req zone=mylimit; proxy_pass http://my_upstream; } }
limit_req_zone指令定義了流量限制相關(guān)的參數(shù),而limit_req指令在出現(xiàn)的上下文中啟用流量限制(示例中,對于”/login/”的所有請求)。limit_req_zone指令通常在 HTTP 塊中定義,使其可在多個上下文中使用,它需要以下三個參數(shù):
1)Key - 定義應(yīng)用限制的請求特性。示例中的 Nginx 變量remote_addr,占用更少的空間)
2)Zone - 定義用于存儲每個 IP 地址狀態(tài)以及被限制請求 URL 訪問頻率的共享內(nèi)存區(qū)域。保存在內(nèi)存共享區(qū)域的信息,意味著可以在 Nginx 的 worker 進(jìn)程之間共享。定義分為兩個部分:通過zone=keyword標(biāo)識區(qū)域的名字,以及冒號后面跟區(qū)域大小。16000 個 IP 地址的狀態(tài)信息,大約需要 1MB,所以示例中區(qū)域可以存儲 160000 個 IP 地址。
3)Rate - 定義最大請求速率。在示例中,速率不能超過每秒 10 個請求。Nginx 實(shí)際上以毫秒的粒度來跟蹤請求,所以速率限制相當(dāng)于每 100 毫秒 1 個請求。因?yàn)椴辉试S”突發(fā)情況”,這意味著在前一個請求 100 毫秒內(nèi)到達(dá)的請求將被拒絕。
當(dāng) Nginx 需要添加新條目時存儲空間不足,將會刪除舊條目。如果釋放的空間仍不夠容納新記錄,Nginx 將會返回 503狀態(tài)碼(Service Temporarily Unavailable)。另外,為了防止內(nèi)存被耗盡,Nginx 每次創(chuàng)建新條目時,最多刪除兩條 60 秒內(nèi)未使用的條目。
limit_req_zone指令設(shè)置流量限制和共享內(nèi)存區(qū)域的參數(shù),但實(shí)際上并不限制請求速率。所以需要通過添加limit_req指令,將流量限制應(yīng)用在特定的 location 或者 server 塊。在上面示例中,我們對/login/請求進(jìn)行流量限制。
現(xiàn)在每個 IP 地址被限制為每秒只能請求 10 次 /login/,更準(zhǔn)確地說,在前一個請求的 100 毫秒內(nèi)不能請求該 URL。
突發(fā)限制訪問頻率(突發(fā)流量)
如果我們在 100 毫秒內(nèi)接收到 2 個請求,怎么辦?對于第二個請求,Nginx 將給客戶端返回狀態(tài)碼 503。這可能并不是我們想要的結(jié)果,因?yàn)閼?yīng)用本質(zhì)上趨向于突發(fā)性。相反地,我們希望緩沖任何超額的請求,然后及時地處理它們。我們更新下配置,在limit_req中使用 burst 參數(shù):
location /login/ { limit_req zone=mylimit burst=20; proxy_pass http://my_upstream; }
burst 參數(shù)定義了超出 zone 指定速率的情況下(示例中的 mylimit 區(qū)域,速率限制在每秒 10 個請求,或每 100 毫秒一個請求),客戶端還能發(fā)起多少請求。上一個請求 100 毫秒內(nèi)到達(dá)的請求將會被放入隊列,我們將隊列大小設(shè)置為 20。
這意味著,如果從一個給定 IP 地址發(fā)送 21 個請求,Nginx 會立即將第一個請求發(fā)送到上游服務(wù)器群,然后將余下 20 個請求放在隊列中。然后每 100 毫秒轉(zhuǎn)發(fā)一個排隊的請求,只有當(dāng)傳入請求使隊列中排隊的請求數(shù)超過 20 時,Nginx 才會向客戶端返回 503。
無延遲的排隊
配置 burst 參數(shù)將會使通訊更流暢,但是可能會不太實(shí)用,因?yàn)樵撆渲脮拐军c(diǎn)看起來很慢。在上面的示例中,隊列中的第 20 個包需要等待 2 秒才能被轉(zhuǎn)發(fā),此時返回給客戶端的響應(yīng)可能不再有用。要解決這個情況,可以在 burst 參數(shù)后添加 nodelay 參數(shù):
location /login/ { limit_req zone=mylimit burst=20 nodelay; proxy_pass http://my_upstream; }
使用 nodelay 參數(shù),Nginx 仍將根據(jù) burst 參數(shù)分配隊列中的位置,并應(yīng)用已配置的速率限制,而不是清理隊列中等待轉(zhuǎn)發(fā)的請求。相反地,當(dāng)一個請求到達(dá)“太早”時,只要在隊列中能分配位置,Nginx 將立即轉(zhuǎn)發(fā)這個請求。將隊列中的該位置標(biāo)記為”taken”(占據(jù)),并且不會被釋放以供另一個請求使用,直到一段時間后才會被釋放(在這個示例中是,100 毫秒后)。
假設(shè)如前所述,隊列中有 20 個空位,從給定的 IP 地址發(fā)出的 21 個請求同時到達(dá)。Ngin x會立即轉(zhuǎn)發(fā)這個 21 個請求,并且標(biāo)記隊列中占據(jù)的 20 個位置,然后每 100 毫秒釋放一個位置。如果是25個請求同時到達(dá),Nginx 將會立即轉(zhuǎn)發(fā)其中的 21 個請求,標(biāo)記隊列中占據(jù)的 20 個位置,并且返回 503 狀態(tài)碼來拒絕剩下的 4 個請求。
現(xiàn)在假設(shè),第一組請求被轉(zhuǎn)發(fā)后 101 毫秒,另 20 個請求同時到達(dá)。隊列中只會有一個位置被釋放,所以 Nginx 轉(zhuǎn)發(fā)一個請求并返回503狀態(tài)碼來拒絕其他 19 個請求。如果在 20 個新請求到達(dá)之前已經(jīng)過去了 501 毫秒,5 個位置被釋放,所以 Nginx 立即轉(zhuǎn)發(fā) 5 個請求并拒絕另外 15 個。
效果相當(dāng)于每秒 10 個請求的“流量限制”。如果希望不限制兩個請求間允許間隔的情況下實(shí)施“流量限制”,nodelay 參數(shù)是很實(shí)用的。
注意:對于大部分部署,我們建議使用 burst 和 nodelay 參數(shù)來配置limit_req指令。
限制并發(fā)連接數(shù)
Nginx 的ngx_http_limit_conn_module模塊提供了對資源連接數(shù)進(jìn)行限制的功能,使用 limit_conn_zone 和 limit_conn 兩個指令就可以了。
properties復(fù)制代碼limit_conn perip 20 : 對應(yīng)的key是 $binary_remote_addr,表示限制單個IP同時最多能持有20個連接。
limit_conn perserver 100 : 對應(yīng)的key是 $server_name,表示虛擬主機(jī)(server) 同時能處理并發(fā)連接的總數(shù)。注意,只有當(dāng) request header 被后端server處理后,這個連接才進(jìn)行計數(shù)。
修改nginx.conf配置,如下:
#速率限流配置 limit_req_zone $binary_remote_addr zone=ipRateLimit:10m rate=2r/s; #并發(fā)量限流-單個IP控制 limit_conn_zone $binary_remote_addr zone=perip:10m; #并發(fā)量限流-整個服務(wù)控制 limit_conn_zone $server_name zone=perserver:10m; server { listen 80; server_name localhost; location ~ .*\.(woff|ico|css|js|gif|jpg|jpeg|png)$ { root /usr/local/openrestyDir/pages/; } location /msitems/ { #限流配置 #limit_req zone=ipRateLimit burst=5 nodelay; #并發(fā)量限流 limit_conn perip 10; limit_conn perserver 100; root /usr/local/openrestyDir/pages/; } }
上面配置了單個IP同時并發(fā)連接數(shù)最多只能10個連接,并且設(shè)置了整個虛擬服務(wù)器同時最大并發(fā)數(shù)最多只能100個鏈接。當(dāng)然,只有當(dāng)請求的header被服務(wù)器處理后,虛擬服務(wù)器的連接數(shù)才會計數(shù)。剛才有提到過Nginx是基于漏桶算法原理實(shí)現(xiàn)的,實(shí)際上限流一般都是基于漏桶算法和令牌桶算法實(shí)現(xiàn)的。接下來我們來看看兩個算法的介紹:
漏桶算法
漏桶算法是網(wǎng)絡(luò)世界中流量整形或速率限制時經(jīng)常使用的一種算法,它的主要目的是控制數(shù)據(jù)注入到網(wǎng)絡(luò)的速率,平滑網(wǎng)絡(luò)上的突發(fā)流量。漏桶算法提供了一種機(jī)制,通過它,突發(fā)流量可以被整形以便為網(wǎng)絡(luò)提供一個穩(wěn)定的流量。也就是我們剛才所講的情況。漏桶算法提供的機(jī)制實(shí)際上就是剛才的案例:突發(fā)流量會進(jìn)入到一個漏桶,漏桶會按照我們定義的速率依次處理請求,如果水流過大也就是突發(fā)流量過大就會直接溢出,則多余的請求會被拒絕。所以漏桶算法能控制數(shù)據(jù)的傳輸速率。
令牌桶算法
令牌桶算法是網(wǎng)絡(luò)流量整形和速率限制中最常使用的一種算法。典型情況下,令牌桶算法用來控制發(fā)送到網(wǎng)絡(luò)上的數(shù)據(jù)的數(shù)目,并允許突發(fā)數(shù)據(jù)的發(fā)送。Google開源項(xiàng)目Guava中的RateLimiter使用的就是令牌桶控制算法。令牌桶算法的機(jī)制如下:存在一個大小固定的令牌桶,會以恒定的速率源源不斷產(chǎn)生令牌。如果令牌消耗速率小于生產(chǎn)令牌的速度,令牌就會一直產(chǎn)生直至裝滿整個令牌桶。
黑白名單
有時候會有一些惡意IP攻擊服務(wù)器,會基于程序頻繁發(fā)起請求對服務(wù)器造成巨大壓力,我們此時可以使用Nginx的黑名單功能實(shí)現(xiàn)黑名單過濾操作。我們首先需要配置黑名單IP,黑名單IP我們可以記錄到一個配置文件中,比如配置到blockip.conf文件中:
配置固定IP為黑名單:
deny 192.168.100.1;
在nginx.conf中引入blockip.conf,可以放到http, server, location語句塊,配置如下:
#黑名單 include blockip.conf;
此時在192.168.100.1的IP上訪問服務(wù)器,會報403錯誤
屏蔽ip的配置文件既可以屏蔽單個ip,也可以屏蔽ip段,或者只允許某個ip或者某個ip段訪問。
# 屏蔽單個ip訪問 deny IP; # 允許單個ip訪問 allow IP; # 屏蔽所有ip訪問 deny all; # 允許所有ip訪問 allow all; #屏蔽整個段即從123.0.0.1到123.255.255.254訪問的命令 deny 123.0.0.0/8 #屏蔽IP段即從123.45.0.1到123.45.255.254訪問的命令 deny 124.45.0.0/16 #屏蔽IP段即從123.45.6.1到123.45.6.254訪問的命令 deny 123.45.6.0/24
如果你想實(shí)現(xiàn)這樣的應(yīng)用,除了幾個IP外,其他全部拒絕,那需要你在blockip.conf中這樣寫:
allow 192.168.100.1; allow 192.168.100.2; deny all;
但是這種手動配置的方式可能太過繁瑣,我們也可以配置動態(tài)黑白名單。
配置動態(tài)黑白名單,我們可以采用Lua+Redis實(shí)現(xiàn),將黑名單存入到Redis緩存,每次執(zhí)行請求時,通過lua腳本先獲取用戶IP,匹配IP是否屬于黑名單,如果是,則不讓請求,如果不是,則放行。
參考鏈接:
https://juejin.cn/post/7120044094239277070
https://cloud.tencent.com/developer/article/1912141
到此這篇關(guān)于nginx 流控使用的項(xiàng)目實(shí)踐的文章就介紹到這了,更多相關(guān)nginx 流控內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Nginx如何實(shí)現(xiàn)pathinfo模式的方法詳解
pathinfo是偽靜態(tài)的一種,對于用過thinkphp的朋友們來說應(yīng)該都不陌生,下面這篇文章主要給大家介紹了關(guān)于Nginx如何實(shí)現(xiàn)pathinfo模式的方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。2017-09-09nginx部署后css、js、圖片等樣式不加載問題的兩種解決方案
這篇文章主要介紹了nginx部署后css、js、圖片等樣式不加載問題的兩種解決方案,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2023-12-12Nginx基礎(chǔ)location語法及功能配置實(shí)例
這篇文章主要為大家介紹了Nginx基礎(chǔ)location語法及功能以及配置實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-03-03詳解Nginx中的geo模塊與利用其配置負(fù)載均衡的示例
這篇文章主要介紹了詳解Nginx中的geo模塊與利用其配置負(fù)載均衡的示例,文中對模塊的geo指令使用有比較詳細(xì)的介紹,需要的朋友可以參考下2016-01-01