Nginx流量控制及白名單實(shí)現(xiàn)
流量限制 (rate-limiting),是Nginx中一個非常實(shí)用,卻經(jīng)常被錯誤理解和錯誤配置的功能。我們可以用來限制用戶在給定時間內(nèi)HTTP請求的數(shù)量。請求,可以是一個簡單網(wǎng)站首頁的GET請求,也可以是登錄表單的 POST 請求。流量限制可以用作安全目的,比如可以減慢暴力密碼破解的速率。通過將傳入請求的速率限制為真實(shí)用戶的典型值,并標(biāo)識目標(biāo)URL地址(通過日志),還可以用來抵御 DDOS 攻擊。更常見的情況,該功能被用來保護(hù)上游應(yīng)用服務(wù)器不被同時太多用戶請求所壓垮。
以下將會介紹Nginx的 流量限制 的基礎(chǔ)知識和高級配置,”流量限制”在Nginx Plus中也適用。
1、Nginx如何限流
Nginx的”流量限制”使用漏桶算法(leaky bucket algorithm),該算法在通訊和分組交換計(jì)算機(jī)網(wǎng)絡(luò)中廣泛使用,用以處理帶寬有限時的突發(fā)情況。就好比,一個桶口在倒水,桶底在漏水的水桶。如果桶口倒水的速率大于桶底的漏水速率,桶里面的水將會溢出;同樣,在請求處理方面,水代表來自客戶端的請求,水桶代表根據(jù)”先進(jìn)先出調(diào)度算法”(FIFO)等待被處理的請求隊(duì)列,桶底漏出的水代表離開緩沖區(qū)被服務(wù)器處理的請求,桶口溢出的水代表被丟棄和不被處理的請求。
2、配置基本的限流
準(zhǔn)備兩臺機(jī)器,關(guān)閉防火墻和selinux
| localhost | Roucky_linux9.4 | 192.168.226.20 |
| localhost | Roucky_linux9.4 | 192.168.226.21 |
都使用nginx官方源下載nginx并啟動
sudo tee /etc/yum.repos.d/nginx.repo << 'EOF' [nginx-stable] name=nginx stable repo baseurl=https://nginx.org/packages/centos/$releasever/$basearch/ gpgcheck=1 enabled=1 gpgkey=https://nginx.org/keys/nginx_signing.key [nginx-mainline] name=nginx mainline repo baseurl=https://nginx.org/packages/mainline/centos/$releasever/$basearch/ gpgcheck=1 enabled=0 gpgkey=https://nginx.org/keys/nginx_signing.key EOF
yum install -y nginx systemctl enable --now nginx
這里還準(zhǔn)備了訪問自動測試的代碼,使用go語言編寫
package main
import (
"fmt"
"io"
"net/http"
"time"
)
// ANSI color codes
const (
RedColor = "\033[31m"
GreenColor = "\033[32m"
YellowColor = "\033[33m"
ResetColor = "\033[0m"
)
// 記錄成功、失敗、無法響應(yīng)以及服務(wù)暫時不可用(503)的請求數(shù)量
var successCount int
var failureCount int
var unresponsiveCount int
var tempUnavailableCount int // 新增變量來跟蹤503 Service Unavailable狀態(tài)的請求數(shù)量
// makeRequest 向給定的 URL 發(fā)送一個 GET 請求,并根據(jù)響應(yīng)的成功與否以不同顏色打印出響應(yīng)狀態(tài)和所花費(fèi)的時間。
func makeRequest(url string, attempt int) {
startTime := time.Now()
resp, err := http.Get(url)
elapsedTime := time.Since(startTime)
if err != nil {
// 如果因?yàn)榫W(wǎng)絡(luò)問題或服務(wù)器問題導(dǎo)致請求失敗,我們將其計(jì)為“無法響應(yīng)”
fmt.Printf("[%d] %sRequest unresponsive: %s %.4f seconds%s\n", attempt, RedColor, err, elapsedTime.Seconds(), ResetColor)
unresponsiveCount++
return
}
defer func(Body io.ReadCloser) {
err := Body.Close()
if err != nil {
fmt.Printf("Error closing response body: %s\n", err)
}
}(resp.Body)
color := GreenColor
if resp.StatusCode == 503 {
color = YellowColor
tempUnavailableCount++ // 對返回503狀態(tài)碼的請求進(jìn)行統(tǒng)計(jì)
} else if resp.StatusCode != 200 {
color = RedColor
failureCount++
} else {
successCount++
}
// 根據(jù)狀態(tài)碼,以對應(yīng)的顏色打印響應(yīng)狀態(tài)碼和耗時
fmt.Printf("[%d] %s%d %.4f seconds%s\n", attempt, color, resp.StatusCode, elapsedTime.Seconds(), ResetColor)
}
func main() {
url := "http://192.168.226.21"
totalAttempts := 1000
startTime := time.Now()
for attempt := 1; attempt <= totalAttempts; attempt++ {
makeRequest(url, attempt)
}
totalElapsedTime := time.Since(startTime)
successRate := (float64(successCount) / float64(totalAttempts)) * 100
failureRate := (float64(failureCount) / float64(totalAttempts)) * 100
unresponsiveRate := (float64(unresponsiveCount) / float64(totalAttempts)) * 100
tempUnavailableRate := (float64(tempUnavailableCount) / float64(totalAttempts)) * 100 // 計(jì)算503狀態(tài)碼比率
fmt.Printf("%sTotal elapsed time: %.4f seconds%s\n", ResetColor, totalElapsedTime.Seconds(), ResetColor)
fmt.Printf("成功率: %.2f%%, 失敗率: %.2f%%, 無法響應(yīng)的請求比: %.2f%%, 服務(wù)暫時不可用請求比率(503): %.2f%%\n", successRate, failureRate, unresponsiveRate, tempUnavailableRate)
}
實(shí)驗(yàn)開始前進(jìn)行訪問1000次測試耗時和成功率

在192.168.226.20主機(jī)操作
“流量限制”配置兩個主要的指令,limit_req_zone和limit_req,如下所示:
在http模塊里配置
# 定義一個限流區(qū)域
# $binary_remote_addr 使用二進(jìn)制格式的客戶端IP地址作為鍵
# zone=mylimit:10m 創(chuàng)建一個名為'mylimit'的共享內(nèi)存區(qū)域,大小為10MB
# rate=10r/s 每秒最多允許1個請求
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
upstream myweb {
server 192.168.226.21:80 weight=1 max_fails=1 fail_timeout=1;
}
在server模塊里配置
server {
listen 80; # 定義服務(wù)器監(jiān)聽的端口為 80,這是 HTTP 協(xié)議的默認(rèn)端口。
server_name localhost; # 設(shè)置服務(wù)器名稱為 localhost,這意味著它將響應(yīng)發(fā)送到 localhost 的請求。
location /{ # 定義對根路徑("/")的請求的處理規(guī)則。
root /usr/share/nginx/html; # 設(shè)置文檔根目錄,這是 Nginx 在響應(yīng)請求時查找文件的地方。
index index.html index.htm; # 設(shè)置當(dāng)請求是一個目錄時,默認(rèn)會返回的文件。在這里,如果訪問根目錄("/"),會首先嘗試返回 index.html 文件,如果沒有找到,再嘗試 index.htm。
limit_req zone=mylimit; # 為根路徑的請求應(yīng)用請求限制,使用名為 mylimit 的限流規(guī)則。
limit_req_dry_run off; # 設(shè)置為on以在日志中查看限制的影響,而不會實(shí)際限制流量
proxy_pass http://myweb;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}#修改默認(rèn)打開頁面,用來區(qū)分兩個主機(jī) #修改192.168.226.20主機(jī) echo "webserver1" > /usr/share/nginx/html/index.html #修改192.168.226.21主機(jī) echo "webserver2" > /usr/share/nginx/html/index.html
#兩個主機(jī)都重啟nginx systemctl restart nginx
瀏覽器訪問192.168.226.20實(shí)際上會看到webserver2的字樣頁面,然后刷新看,有失敗和成功頁面,就完成了基本的限流設(shè)置。跑完go代碼看結(jié)果如果(比率是有一點(diǎn)波動的是正常的):

limit_req_zone指令定義了流量限制相關(guān)的參數(shù),而limit_req指令在出現(xiàn)的上下文中啟用流量限制(示例中,對于”/login/”的所有請求)。
limit_req_zone指令通常在HTTP塊中定義,使其可在多個上下文中使用,它需要以下三個參數(shù):
Key - 定義應(yīng)用限制的請求特性。示例中的 Nginx 變量
$binary_remote_addr,保存客戶端IP地址的二進(jìn)制形式。這意味著,我們可以將每個不同的IP地址限制到,通過第三個參數(shù)設(shè)置的請求速率。(使用該變量是因?yàn)楸茸址问降目蛻舳薎P地址$remote_addr,占用更少的空間)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地址。Rate - 定義最大請求速率。在示例中,速率不能超過每秒10個請求。Nginx實(shí)際上以毫秒的粒度來跟蹤請求,所以速率限制相當(dāng)于每100毫秒1個請求。因?yàn)椴辉试S”突發(fā)情況”(見下一章節(jié)),這意味著在前一個請求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。
3、處理突發(fā)
如果我們在100毫秒內(nèi)接收到2個請求,怎么辦?對于第二個請求,Nginx將給客戶端返回狀態(tài)碼503。這可能并不是我們想要的結(jié)果,因?yàn)閼?yīng)用本質(zhì)上趨向于突發(fā)性。相反地,我們希望緩沖任何超額的請求,然后及時地處理它們。我們更新下配置,在limit_req中使用burst參數(shù):

重啟nginx然后運(yùn)行g(shù)o代碼請求測試

burst參數(shù)定義了當(dāng)請求速率超過rate參數(shù)所設(shè)定的限制時,允許額外處理的請求數(shù)量。這些額外的請求將被暫時放入一個隊(duì)列中等待處理,而不是立即返回錯誤。但是訪問量大的話后面的排隊(duì)時間就會太慢,并不是最優(yōu)的選擇。
burst參數(shù)定義了超出zone指定速率的情況下(示例中的mylimit區(qū)域,速率限制在每秒10個請求,或每100毫秒一個請求),客戶端還能發(fā)起多少請求。上一個請求100毫秒內(nèi)到達(dá)的請求將會被放入隊(duì)列,我們將隊(duì)列大小設(shè)置為20。
這意味著,如果從一個給定IP地址發(fā)送21個請求,Nginx會立即將第一個請求發(fā)送到上游服務(wù)器群,然后將余下20個請求放在隊(duì)列中。然后每100毫秒轉(zhuǎn)發(fā)一個排隊(duì)的請求,只有當(dāng)傳入請求使隊(duì)列中排隊(duì)的請求數(shù)超過20時,Nginx才會向客戶端返回503。
4、無延遲的排隊(duì)
配置burst參數(shù)將會使通訊更流暢,但是可能會不太實(shí)用,因?yàn)樵撆渲脮拐军c(diǎn)看起來很慢。在上面的示例中,隊(duì)列中的第20個包需要等待2秒才能被轉(zhuǎn)發(fā),此時返回給客戶端的響應(yīng)可能不再有用。要解決這個情況,可以在burst參數(shù)后添加nodelay參數(shù):

重啟nginx運(yùn)行g(shù)o測試代碼

使用nodelay參數(shù),Nginx仍將根據(jù)burst參數(shù)分配隊(duì)列中的位置,并應(yīng)用已配置的速率限制,而不是清理隊(duì)列中等待轉(zhuǎn)發(fā)的請求。相反地,當(dāng)一個請求到達(dá)“太早”時,只要在隊(duì)列中能分配位置,Nginx將立即轉(zhuǎn)發(fā)這個請求。將隊(duì)列中的該位置標(biāo)記為”taken”(占據(jù)),并且不會被釋放以供另一個請求使用,直到一段時間后才會被釋放(在這個示例中是,100毫秒后)。
假設(shè)如前所述,隊(duì)列中有20個空位,從給定的IP地址發(fā)出的21個請求同時到達(dá)。Nginx會立即轉(zhuǎn)發(fā)這個21個請求,并且標(biāo)記隊(duì)列中占據(jù)的20個位置,然后每100毫秒釋放一個位置。如果是25個請求同時到達(dá),Nginx將會立即轉(zhuǎn)發(fā)其中的21個請求,標(biāo)記隊(duì)列中占據(jù)的20個位置,并且返回503狀態(tài)碼來拒絕剩下的4個請求。
現(xiàn)在假設(shè),第一組請求被轉(zhuǎn)發(fā)后101毫秒,另20個請求同時到達(dá)。隊(duì)列中只會有一個位置被釋放,所以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指令。
5、高級配置示例
通過將基本的“流量限制”與其他Nginx功能配合使用,我們可以實(shí)現(xiàn)更細(xì)粒度的流量限制。
1、白名單
下面這個例子需要將上面做過的刪除,然后重新配置
#排除上面實(shí)驗(yàn)的干擾,重新安裝配置nginx yum remove -y nginx yum install -y nginx systemctl enable --now nginx
下面這個例子將展示,如何對任何不在白名單內(nèi)的請求強(qiáng)制執(zhí)行“流量限制”:
vim /etc/nginx/nginx.conf
將下面的http塊替換nginx配置文件的里的http塊代碼,其他不用動
#將下面的http塊替換nginx配置文件的里的http塊代碼,其他不用動
http {
include /etc/nginx/mime.types; # 包括MIME類型定義,讓Nginx能根據(jù)文件擴(kuò)展名設(shè)置正確的Content-Type頭。
default_type application/octet-stream; # 設(shè)置默認(rèn)的MIME類型,當(dāng)文件類型未定義時使用。
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'; # 自定義日志格式。
access_log /var/log/nginx/access.log main; # 定義access日志的存儲位置和使用的格式。
# 以下部分定義了基于IP地址的訪問限制。
geo $limit {
default 1; # 默認(rèn)情況下,所有IP地址的$limit值設(shè)為1。
10.0.0.0/24 0; # 對于這兩個子網(wǎng)中的IP地址,將$limit設(shè)為0。
192.168.0.0/24 0;
}
# 根據(jù)$limit的值,動態(tài)地設(shè)置$limit_key變量。
map $limit $limit_key {
0 ""; # 如果$limit為0,$limit_key為空。
1 $binary_remote_addr; # 如果$limit為1,$limit_key使用二進(jìn)制格式的客戶端IP地址。
}
# 定義請求限制區(qū)域req_zone,按$limit_key對請求進(jìn)行分組,每個組最多每秒處理5個請求。
limit_req_zone $limit_key zone=req_zone:10m rate=5r/s;
server { # 定義一個服務(wù)器監(jiān)聽在80端口。
listen 80; # 監(jiān)聽80端口。
server_name localhost; # 服務(wù)器名稱設(shè)置為localhost。
location / { # 對于根路徑的請求。
limit_req zone=req_zone burst=10 nodelay; # 應(yīng)用請求限制,允許突發(fā)請求高達(dá)10個。
root /usr/share/nginx/html; # 網(wǎng)站根目錄。
index index.html index.hml; # 定義默認(rèn)首頁。
}
}
include /etc/nginx/conf.d/*.conf; # 導(dǎo)入/etc/nginx/conf.d/目錄下的所有.conf配置文件。
}
這個例子同時使用了geo和map指令。geo塊將給在白名單中的IP地址對應(yīng)的$limit變量分配一個值0,給其它不在白名單中的分配一個值1。然后我們使用一個映射將這些值轉(zhuǎn)為key,如下:
如果
$limit變量的值是0,$limit_key變量將被賦值為空字符串如果
$limit變量的值是1,$limit_key變量將被賦值為客戶端二進(jìn)制形式的IP地址
兩個指令配合使用,白名單內(nèi)IP地址的$limit_key變量被賦值為空字符串,不在白名單內(nèi)的被賦值為客戶端的IP地址。當(dāng)limit_req_zone后的第一個參數(shù)是空字符串時,不會應(yīng)用“流量限制”,所以白名單內(nèi)的IP地址(10.0.0.0/24和192.168.0.0/24 網(wǎng)段內(nèi))不會被限制。其它所有IP地址都會被限制到每秒5個請求。
limit_req指令將限制應(yīng)用到/的location塊,允許在配置的限制上最多超過10個數(shù)據(jù)包的突發(fā),并且不會延遲轉(zhuǎn)發(fā)。
2、location 包含多l(xiāng)imit_req指令
我們可以在一個location塊中配置多個limit_req指令。符合給定請求的所有限制都被應(yīng)用時,意味著將采用最嚴(yán)格的那個限制。例如,多個指令都制定了延遲,將采用最長的那個延遲。同樣,請求受部分指令影響被拒絕,即使其他指令允許通過也無濟(jì)于事。
擴(kuò)展前面將“流量限制”應(yīng)用到白名單內(nèi)IP地址的例子:
http {
# ...
limit_req_zone $limit_key zone=req_zone:10m rate=5r/s;
limit_req_zone $binary_remote_addr zone=req_zone_wl:10m rate=15r/s;
server {
# ...
location / {
limit_req zone=req_zone burst=10 nodelay;
limit_req zone=req_zone_wl burst=20 nodelay;
# ...
}
}
}
白名單內(nèi)的IP地址不會匹配到第一個“流量限制”,而是會匹配到第二個`req_zone_wl`,并且被限制到每秒15個請求。
不在白名單內(nèi)的IP地址兩個限制能匹配到,所以應(yīng)用限制更強(qiáng)的那個:每秒5個請求。因此理解了原理,修改上面的http塊里的代碼進(jìn)行測試:
#將下面的http塊替換nginx配置文件的里的http塊代碼,其他不用動
http {
include /etc/nginx/mime.types; # 包括MIME類型定義,讓Nginx能根據(jù)文件擴(kuò)展名設(shè)置正確的Content-Type頭。
default_type application/octet-stream; # 設(shè)置默認(rèn)的MIME類型,當(dāng)文件類型未定義時使用。
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'; # 自定義日志格式。
access_log /var/log/nginx/access.log main; # 定義access日志的存儲位置和使用的格式。
# 以下部分定義了基于IP地址的訪問限制。
geo $limit {
default 1;
10.0.0.0/24 0;
192.168.0.0/24 0;
}
# 根據(jù)$limit的值,動態(tài)地設(shè)置$limit_key變量。
map $limit $limit_key {
0 ""; # 如果$limit為0,$limit_key為空。
1 $binary_remote_addr; # 如果$limit為1,$limit_key使用二進(jìn)制格式的客戶端IP地址。
}
# 定義請求限制區(qū)域req_zone,按$limit_key對請求進(jìn)行分組,每個組最多每秒處理5個請求。
limit_req_zone $limit_key zone=req_zone:10m rate=5r/s;
limit_req_zone $binary_remote_addr zone=req_zone_wl:10m rate=15r/s;
server { # 定義一個服務(wù)器監(jiān)聽在80端口。
listen 80; # 監(jiān)聽80端口。
server_name localhost; # 服務(wù)器名稱設(shè)置為localhost。
location / { # 對于根路徑的請求。
limit_req zone=req_zone burst=10 nodelay;
limit_req zone=req_zone_wl burst=20 nodelay;
root /usr/share/nginx/html; # 網(wǎng)站根目錄。
index index.html index.hml; # 定義默認(rèn)首頁。
}
}
include /etc/nginx/conf.d/*.conf; # 導(dǎo)入/etc/nginx/conf.d/目錄下的所有.conf配置文件。
}重啟nginx測試:

接下來將白名單和黑名單調(diào)換

重啟nginx并測試

因此:白名單內(nèi)的IP地址不會匹配到第一個“流量限制”,而是會匹配到第二個req_zone_wl,并且被限制到每秒15個請求。不在白名單內(nèi)的IP地址兩個限制能匹配到,所以應(yīng)用限制更強(qiáng)的那個:每秒5個請求是正確的。
6、配置流量控制相關(guān)功能
1、配置日志記錄
默認(rèn)情況下,Nginx會在日志中記錄由于流量限制而延遲或丟棄的請求,如下所示:
2024/06/20 20:20:00 [error] 120315#0: *32086 limiting requests, excess: 1.000 by zone "mylimit", client: 192.168.226.20, server: nginx.com, request: "GET / HTTP/1.0", host: "nginx.com"
日志條目中包含的字段:
limiting requests - 表明日志條目記錄的是被“流量限制”請求
excess - 每毫秒超過對應(yīng)“流量限制”配置的請求數(shù)量
zone - 定義實(shí)施“流量限制”的區(qū)域
client - 發(fā)起請求的客戶端IP地址
server - 服務(wù)器IP地址或主機(jī)名
request - 客戶端發(fā)起的實(shí)際HTTP請求
host - HTTP報頭中host的值
Nginx 的 limit_req_log_level 指令用于定義當(dāng)請求速率超出 limit_req 指定的速率限制時,日志記錄的級別。這允許你對因超出請求速率限制而被延遲或拒絕的請求進(jìn)行特定級別的日志記錄,從而能夠更靈活地處理這些日志信息,而不必改變?nèi)值腻e誤日志級別。
limit_req_log_level 指令支持的日志級別包括:
- info: 記錄基礎(chǔ)信息,這是默認(rèn)設(shè)置。
- notice: 記錄正常但重要的情況。
- warn: 記錄更嚴(yán)重的警告信息。
- error: 記錄錯誤信息,這個設(shè)置通常用于希望對超限請求進(jìn)行更加突出顯示的場景。
默認(rèn)情況下,Nginx以error級別來記錄被拒絕的請求,如上面示例中的[error]所示(Ngin以較低級別記錄延時請求,一般是info級別)。如要更改Nginx的日志記錄級別,需要使用limit_req_log_level指令。這里,我將被拒絕請求的日志記錄級別設(shè)置為warn:
limit_req_zone $binary_remote_addr zone=myzone:10m rate=1r/s;
server {
location / {
limit_req zone=myzone burst=5 nodelay;
limit_req_log_level warn;
...
}
}在上面的例子中,limit_req_zone 指令定義了一個名為 myzone 的速率限制區(qū)域,限制速率為每秒1個請求。在 server 塊的 location 部分,通過 limit_req 應(yīng)用了這個速率限制,并且設(shè)置了 burst 參數(shù)為5,表示允許短時間內(nèi)超出速率限制的請求在不被立即拒絕的情況下排隊(duì)等待處理。更重要的是,通過 limit_req_log_level warn 指令,指定了當(dāng)請求被延遲或拒絕時,這些事件將以 warn 級別記錄在日志中。這意味著只有當(dāng)請求因?yàn)槌鏊俾氏拗贫谎舆t或拒絕時,才會在日志中以警告級別記錄,從而使這類事件在日志文件中更加突出,便于管理員進(jìn)行分析和監(jiān)控。
擴(kuò)展日志記錄級別:
注意區(qū)別這兩個日志對應(yīng)的層級關(guān)系和定義
Nginx 的日志記錄級別用于控制日志中記錄信息的詳細(xì)程度。在 Nginx 中,你可以為錯誤日志(error_log 指令)設(shè)置不同的日志級別,這些級別從最低到最高包括:
debug: 提供最詳盡的日志信息,包括調(diào)試信息。這個級別記錄所有的詳細(xì)操作,對于開發(fā)或調(diào)試非常有用,但在生產(chǎn)環(huán)境中會生成大量日志信息。
info: 記錄基礎(chǔ)的信息性消息,除了
debug級別的信息。notice: 記錄正常但重要的條件。默認(rèn)級別,標(biāo)準(zhǔn)的錯誤和重要信息都會被記錄。
warn: 記錄警告信息,例如使用了非標(biāo)準(zhǔn)的配置指令或者有潛在的錯誤。
error: 記錄處理請求時發(fā)生的錯誤,但不會阻止服務(wù)運(yùn)行的錯誤信息。
crit: 記錄臨界條件錯誤,比如嚴(yán)重的硬件或軟件錯誤。
alert: 要求立即采取行動的情況,如系統(tǒng)運(yùn)行環(huán)境出現(xiàn)了非常嚴(yán)重的問題。
emerg: 記錄緊急情況,如系統(tǒng)不可用的情況。
配置錯誤日志級別的語法如下:
error_log /path/to/your/error.log level;
這里,/path/to/your/error.log 是想要保存錯誤日志的文件路徑,level 是上面提到的日志級別之一。如果不指定級別,error 級別會被使用。
在配置日志時,選擇適當(dāng)?shù)娜罩炯墑e對于優(yōu)化性能和管理日志文件大小很重要。例如,在開發(fā)環(huán)境中,可能會使用 debug 級別以便獲取盡可能多的信息來調(diào)試應(yīng)用。然而,在生產(chǎn)環(huán)境中,可能會選擇 notice 或 warn 級別,來減少日志文件的大小并關(guān)注更重要的系統(tǒng)消息。
2、發(fā)送到客戶端的錯誤代碼
一般情況下,客戶端超過配置的流量限制時,Nginx響應(yīng)狀態(tài)碼為503(Service Temporarily Unavailable)??梢允褂?code>limit_req_status指令來設(shè)置為其它狀態(tài)碼(例如下面的412狀態(tài)碼):
可選擇范圍大約在400-599之間,并盡量避免與已存在的狀態(tài)碼產(chǎn)生沖突,造成歧義。
續(xù)接上面的配置,只需要在server模塊中的location模塊中加入一個參數(shù)為
limit_req_status 412;
添加的位置如圖說式:

重啟nginx
systemctl restart nginx
測試查看:

這里是因?yàn)槲业膅o代碼的bug顯示黃色,因?yàn)閾Q了裝填嗎顯示成失敗對應(yīng)的紅色,但其實(shí)已經(jīng)從默認(rèn)的503狀態(tài)碼切換到指定的412狀態(tài)碼了。
7、nginx 流量控制總結(jié)
以上已經(jīng)涵蓋了Nginx和Nginx Plus提供的“流量限制”的很多功能,包括為HTTP請求的不同loation設(shè)置請求速率,給“流量限制”配置burst和nodelay參數(shù)。還涵蓋了針對客戶端IP地址的白名單和黑名單應(yīng)用不同“流量限制”的高級配置,闡述了如何去日志記錄被拒絕和延時的請求。
到此這篇關(guān)于Nginx流量控制實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Nginx流量控制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Nginx報錯host not found in upstream的解決辦法
本文主要介紹了Nginx報錯host not found in upstream的解決辦法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08
Nginx服務(wù)器設(shè)置網(wǎng)站驗(yàn)證訪問的方法
這篇文章主要介紹了Nginx服務(wù)器設(shè)置網(wǎng)站驗(yàn)證訪問的方法,通過設(shè)置密碼來要求登錄網(wǎng)站目錄的用戶進(jìn)行驗(yàn)證,需要的朋友可以參考下2015-07-07
windows系統(tǒng)下安裝Nginx及簡單使用過程
Nginx是一個很強(qiáng)大的高性能Web和反向代理服務(wù),也是一種輕量級的Web服務(wù)器,可以作為獨(dú)立的服務(wù)器部署網(wǎng)站,應(yīng)用非常廣泛,特別是現(xiàn)在前后端分離的情況下,這篇文章主要介紹了windows系統(tǒng)下安裝Nginx以及簡單使用,需要的朋友可以參考下2024-04-04
nginx有哪些常規(guī)調(diào)優(yōu)手段詳解
性能調(diào)優(yōu)就是用更少的資源提供更好的服務(wù),成本利益最大化,下面這篇文章主要給大家介紹了關(guān)于nginx有哪些常規(guī)調(diào)優(yōu)手段的相關(guān)資料,需要的朋友可以參考下2023-01-01
Nginx日志定期清理設(shè)置實(shí)現(xiàn)
本文主要介紹了Nginx日志定期清理設(shè)置實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-12-12

