Nginx限流


文章原創於公眾號:程序猿周先森。本平台不定時更新,喜歡我的文章,歡迎關注我的微信公眾號。
file

在當今流量徒增的互聯網時代,很多業務場景都會涉及到高並發。這個時候接口進行限流是非常有必要的,而限流是Nginx最有用的特性之一,而且也是最容易被錯誤配置的特性之一。本篇文章主要講講Nginx如何對接口進行限流。

Nginx限流主要分為兩種方式:

  • 限制訪問頻率
  • 限制並發連接數

為什么需要限流?開源人員可以通過限流限制訪問速度來防止外部暴力掃描,或者減少密碼被暴力破解的可能性。也可以解決流量突發問題(如線上活動導致訪問量突增)。用一句話來概括就是說限流是用於保護服務器不會因為承受不住同一時刻的大量並發請求而宕機。接下來我們分別來看看Nginx的兩種限流方式:

限制訪問頻率
限制訪問頻率其實需要分成兩種情況:正常情況下進行訪問頻率限制以及流量突發情況下進行訪問頻率限制。我們分別看看這兩種情況下Nginx是如何進行處理的:

正常流量限制訪問頻率
Nginx中使用ngx_http_limit_req_module模塊來限制的訪問頻率,限制的原理實質是基於漏桶算法原理來實現的。在nginx.conf配置文件中可以使用limit_req_zone命令及limit_req命令限制單個IP的請求處理頻率。

我們可以先來看看這兩個命令的語法結構:

  • limit_req_zone key zone rate

對於上面語法結構的參數簡單做下解釋:

  • key: 定義需要限流的對象。
  • zone: 定義共享內存區來存儲訪問信息。
  • rate: 用於設置最大訪問速率。

接下來我們看個簡單的例子:

http {
limit_req_zone $binary_remote_addr zone=myLimit:10m rate=3r/s;
}

server {
location / {
limit_req zone=myLimit;
rewrite / http://www.niyueling.cn permanent;
}
}

對配置簡單做下解釋:
上面binary_remote_addr就是key,表示基於客戶端ip(remote_addr)進行限流,binary_表示壓縮內存占用量。定義了一個大小為10M,名稱為myLimit的內存區,用於存儲IP地址訪問信息。rate設置IP訪問頻率,rate=5r/s表示每秒只能處理每個IP地址的5個請求。Nginx限流是按照毫秒級為單位的,也就是說1秒處理5個請求會變成每200ms只處理一個請求。如果200ms內已經處理完1個請求,但是還是有有新的請求到達,這時候Nginx就會拒絕處理該請求。

突發流量限制訪問頻率
上面的配置一定程度可以限制訪問頻率,但是也存在着一個問題:如果突發流量超出請求被拒絕處理,無法處理活動時候的突發流量,這時候應該如何進一步處理呢?Nginx提供burst參數結合nodelay參數可以解決流量突發的問題,可以設置能處理的超過設置的請求數外能額外處理的請求數。我們可以將之前的例子添加burst參數以及nodelay參數:

http {
limit_req_zone $binary_remote_addr zone=myLimit:10m rate=3r/s;
}

server {
location / {
limit_req zone=myLimit burst=5 nodelay;
rewrite / http://www.niyueling.cn permanent;
}
}

可以看到我在原有的location中的limit_req指令中添加了burst=5 nodelay,如果沒有添加nodelay參數,則可以理解為預先在內存中占用了5個請求的位置,如果有5個突發請求就會按照200ms去依次處理請求,也就是1s內把5個請求全部處理完畢。如果1s內有新的請求到達也不會立即進行處理,因為緊急程度更低。這樣實際上就會將額外的5個突發請求以200ms/個去依次處理,保證了處理速率的穩定,所以在處理突發流量的時候也一樣可以正常處理。如果添加了nodelay參數則表示要立即處理這5個突發請求。

限制並發連接數
Nginx中的ngx_http_limit_conn_module模塊提供了限制並發連接數的功能,可以使用limit_conn_zone指令以及limit_conn執行進行配置。接下來我們可以通過一個簡單的例子來看下:

http {
limit_conn_zone $binary_remote_addr zone=myip:10m;
limit_conn_zone $server_name zone=myServerName:10m;
}

server {
location / {
limit_conn myip 10;
limit_conn myServerName 100;
rewrite / http://www.niyueling.cn permanent;
}
}

上面配置了單個IP同時並發連接數最多只能10個連接,並且設置了整個虛擬服務器同時最大並發數最多只能100個鏈接。當然,只有當請求的header被服務器處理后,虛擬服務器的連接數才會計數。剛才有提到過Nginx是基於漏桶算法原理實現的,實際上限流一般都是基於漏桶算法和令牌桶算法實現的。接下來我們來看看兩個算法的介紹:

漏桶算法
漏桶算法是網絡世界中流量整形或速率限制時經常使用的一種算法,它的主要目的是控制數據注入到網絡的速率,平滑網絡上的突發流量。漏桶算法提供了一種機制,通過它,突發流量可以被整形以便為網絡提供一個穩定的流量。也就是我們剛才所講的情況。漏桶算法提供的機制實際上就是剛才的案例:突發流量會進入到一個漏桶,漏桶會按照我們定義的速率依次處理請求,如果水流過大也就是突發流量過大就會直接溢出,則多余的請求會被拒絕。所以漏桶算法能控制數據的傳輸速率。
file

令牌桶算法
令牌桶算法是網絡流量整形和速率限制中最常使用的一種算法。典型情況下,令牌桶算法用來控制發送到網絡上的數據的數目,並允許突發數據的發送。Google開源項目Guava中的RateLimiter使用的就是令牌桶控制算法。令牌桶算法的機制如下:存在一個大小固定的令牌桶,會以恆定的速率源源不斷產生令牌。如果令牌消耗速率小於生產令牌的速度,令牌就會一直產生直至裝滿整個令牌桶。
file
file

漏桶算法與令牌桶算法的區別
兩種算法都能夠限制數據傳輸速率,但令牌桶還允許某種程度的突發傳輸。因為令牌桶算法只要令牌桶中存在令牌,那么就可以突發的傳輸對應的數據到目的地,所以更適合流量突發的情形下進行使用。

如果喜歡我的文章,歡迎關注我的個人公眾號
file


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM