NGINX:在佇列中查詢的請求限制逾時行為(突發)

NGINX:在佇列中查詢的請求限制逾時行為(突發)

目前,我們的佇列大小為 3000 個請求。

location /api/v2 {
     limit_req zone=bursted burst=3000;
     include /etc/nginx/proxy.conf;
 }

速率限制為每秒 10 個請求。

 limit_req_zone $limit zone=api_slow:10m rate=1r/s;
 limit_req_zone $server_name zone=bursted:10m rate=10r/s;

保持活動超時為 30 秒。換句話說,當佇列已滿時,每 30 秒應拒絕 2700 個請求,並顯示錯誤代碼 408。

 reset_timedout_connection on;
 client_body_timeout 10;
 send_timeout 2;
 keepalive_timeout 30;

在高峰時段,我在日誌中找不到任何請求,由於逾時,該請求被 NGINX 拒絕,錯誤代碼為 408,而請求正在佇列中等待轉發到 servlet 容器。僅拒絕並傳回 503 錯誤代碼,這與請求速率開銷相對應。

delaying request, excess: 2958.320, by zone "bursted"
limiting requests, excess: 3000.730 by zone "bursted"

如果此類佇列中的請求掛起時間過長,NGINX 是否會透過逾時拒絕這些請求?這個超時是什麼?它的配置在哪裡?

答案1

nginx 速率限制和逾時的工作原理似乎有點混亂。沒有暫停用於速率限制。您只需設定速率和隊列大小。任何超出速率的請求都會新增至佇列中以供稍後處理。一旦佇列完全填滿,任何其他請求都將被拒絕,並顯示 503 狀態代碼。


在你的例子中您已將速率設定為每秒 10 個請求 (10r/s),突發大小為 3000,區域「突發」大小為 10 MB。此速率限制適用於每個定義的伺服器的單獨計數。

換句話說,您的伺服器每 0.1 秒接受並處理一個請求,並且最多可以排隊 3000 個超出的請求,然後以定義的速率處理這些請求:每 0.1 秒一個。您的突發區域可儲存約 160.000 個 IP 位址。

這意味著如果 1 秒內有 3011 個請求到達,nginx 會立即處理前 10 個請求,並將另外 3000 個請求放入佇列中,第 3011 個請求將被拒絕,狀態碼為 503。然後,佇列將以每 0.1 秒一個請求的定義速率進行處理。只要沒有新的請求到達,隊列就會變短,新的請求可以再次加入隊列。但是,雖然佇列已容納 3000 個請求,但每個額外的請求都將被拒絕,並顯示 503 狀態代碼。

這種突發隊列的線性處理行為可能會使您的網站看起來緩慢。為了防止這種情況,您可以將nodelay參數加到limit_req zone=bursted burst=3000 nodelay;.這將使突發佇列中的所有請求立即處理,同時將佇列中的插槽標記為“已佔用”,然後再次以定義的速率逐個插槽“釋放”,以便隨著時間的推移滿足定義的速率限制。

limit_req_status 444;順便說一句:您可以透過新增至設定區塊來將拒絕請求的狀態代碼從 503 變更為 444 http

欲了解更多詳情,請參閱:


您的配置中的兩個逾時:

client_body_timeout 10;將使您的伺服器在請求後等待最多 10 秒才能發送客戶端正文。如果在此時間內用戶端沒有傳送正文,伺服器將關閉連線並傳回 408 狀態碼。

keepalive_timeout 30;將使您的伺服器關閉 30 秒後仍然打開的與客戶端的所有連線。但根據我的測試,請求在突發佇列中等待的時間不計入keepalive_timeout。


執行負載測試使用ab或者圍城

相關內容