Ngixn 限流配置實戰(zhàn)

為什么需要限流

如果你的后端服務器只能支持10QPS的并發(fā)量, 當用戶量突然暴漲或者有CC攻擊的時候并發(fā)量將遠遠大于這個值, 為了避免大量的請求導致后端服務器CPU/Memory異常, 或則導致后端數據庫異常而導致的崩潰, 這時候我們需要對服務進行'限流降級', 保證服務器不崩潰, 這總比崩潰之后導致所有人都不能使用好.

為Nginx配置限流

Nginx默認是不限流的, 需要我們手動配置開啟限流.

在conf配置文件的任何地方 寫下 限流規(guī)則的定義.

語法如下:

limit_req_zone key zone=name:size rate=rate [sync];

例如

limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s;
limit_req_zone $http_host zone=perhost:10m rate=10r/s;

上面的兩個指令的意思大致為:

使用 limit_req_zone 規(guī)則給每一個Ip($binary_remote_addr) 限流, 區(qū)域(即名字)為perip, 容量為10M, 限制速率為每秒10次.

其中 key 可以是內置的變量, 或者自定義的變量, 更多寫法可以參閱官方文檔: ngx_http_limit_req_module.html#limit_req_zone.

然后在 server 或者 location 上下文中使用定義的規(guī)則:

server {
    listen       80;
    server_name  localhost;
    ...
    limit_req zone=perip burst=5 nodelay;
    limit_req zone=perhost burst=5 nodelay;
    ...
}

上面兩個指令的意思大致為:

使用perip區(qū)域(即名字)來限制流量, 還有兩項配置: burst 和 nodelay. 這兩個配置需要重點理解.

  • burst: 譯名 爆發(fā), 意思是如果請求速率超過了配置的速率(本例中是10次/s), 則還可以將5個請求放入緩沖區(qū), 等到下一秒再處理這5個請求.
  • nodelay: 表示如何處理緩存區(qū)(即burst)中的請求, 如果設置了nodelay, 則緩沖區(qū)里的請求會 都會被排隊等待處理.

深入理解 burst 和 nodelay 的作用

我們用例子繼續(xù)理解 burst 和 nodelay.

1. rate = 10r/s

即每100ms只能處理一個請求, 當在同一個時間段(如0-100ms)內有兩個請求時, 第二個請求將會被丟棄.

2. rate = 10r/s burst = 5

在上面的例子中, 我們發(fā)現當有2個請求而還達不到速率10r/s的情況下, 就會有請求被丟棄, 但現實中網絡由于有延遲, 就算用戶是勻速訪問, 都會出現多個請求同時到達服務器的情況, 這會導致大量的請求被錯誤丟棄.

我們可以使用 brust 來優(yōu)化這個問題.

現在我們將burst設置為5

  • 如果在100ms以內有2個請求同時到達Nginx, 則第2個請求會先被Nginx放在緩沖區(qū), 直到下一個100ms(即100ms-200ms時間段)時處理第2個請求.
  • 如果在100ms以內有7個請求同時到達Nginx, 則第2-6(共5個)個請求會先被Nginx放在緩沖區(qū), 第7個請求由于超過了緩沖區(qū)大小會被丟棄, 之后每100ms從緩沖區(qū)中取出一個請求處理, 也就是說在100ms-200ms時間段開始處理第2個請求, 并且又可以新接入第8個請求. 可以預見, 處理第6請求將會多等待 5 *100ms = 500ms 的時間, 緩存區(qū)越大, 等待時間會越長, 當然也不可能一直等待, nginx也有超時機制, 超時的請求會直接返回錯誤.

3. rate = 10r/s burst = 5 nodelay

為了解決上例中等待時間過長的問題, 還可以設置 nodelay.

和上例唯一不同的是, 當有多個請求在緩沖區(qū)時, 這多個請求將會同時被處理, 而不是每100ms處理一個.

  • 如果在100ms以內有2個請求同時到達Nginx, 則第2個請求會先被Nginx放在緩沖區(qū), 并同時處理第2個請求.
  • 如果在100ms以內有7個請求同時到達Nginx, 則第2-6(共5個)個請求會先被Nginx放在緩沖區(qū), 第7個請求由于超過了緩沖區(qū)大小會被丟棄, 在緩沖區(qū)中的5個請求也會被同時處理(這時有6個請求在這一時刻被nginx同時處理). 之后每100ms釋放一個緩沖區(qū)讓新的請求進來. 最后得到的結果是: 突發(fā)請求下, 在開始的0-100ms時間段內可以處理6個請求, 然后每100ms再處理一個請求, 最后速率還是會穩(wěn)定在10r/s左右.

總結

何時會丟棄請求

如果沒有配置 burst, 則在一個時區(qū)(如設置了rate=100/s, 則一個時區(qū)是10ms)內只能有一個請求, 剩下的請求都會被丟棄.

如果配置了 burst, 則在一個時區(qū)中第一個請求之后的所有請求會先放入緩沖區(qū), 當緩沖區(qū)滿了之后, 之后的請求都會被丟棄.

最佳實踐

rate + burst + nodelay 是最理想的方案, 將最大限度的保證可用, 但也會對后端服務器造成更大的壓力, 因為瞬時并發(fā)會更大. 關于如何根據后端服務器支持的QPS配置最佳的rate與burst的值, 作者還沒有仔細研究, 目前靠猜, 我的方案是 rate = burst = QPS

如果你實在害怕后端服務器被壓垮, 則使用 rate + burst 方案也不錯, 它保證每100ms只會有1個請求被處理.

參考

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 【轉載請注明出處】:http://www.itdecent.cn/p/790373b4903b 生活中的 “限流...
    后端老鳥閱讀 582評論 0 1
  • 作者:大魚燉海棠鏈接:http://www.itdecent.cn/p/2c6e7852e732 系統(tǒng)設計時一般...
    一劍仙人跪_閱讀 439評論 0 0
  • 系統(tǒng)設計時一般會預估負載,當系統(tǒng)遭受惡意攻擊或正常突發(fā)流量等都可能導致系統(tǒng)被壓垮,而限流就是保護措施之一。 一、限...
    大魚燉海棠閱讀 1,801評論 2 43
  • 限流算法: 1. 令牌桶算法 算法思想是: 令牌以固定速率產生,并緩存到令牌桶中;令牌桶放滿時,多余的令牌被丟棄;...
    touch_The_Sky閱讀 980評論 0 2
  • 系統(tǒng)設計時一般會預估負載,當系統(tǒng)暴露在公網中時,惡意攻擊或正常突發(fā)流量等都可能導致系統(tǒng)被壓垮,而限流就是保護措施之...
    非資深技術人閱讀 2,251評論 0 0

友情鏈接更多精彩內容