天天看點

Nginx 如何限流和通路控制(詳解)

文章目錄

    • 前言
    • 一、Nginx限流
      • 1、簡介
      • 2、關于 limit_req 和 limit_conn 的差別
      • 3、limit_conn 子產品
        • (1)limit_conn_zone
        • (2)limit_conn
        • (3)limit_conn_log_level
        • (4)limit_conn_status code
        • (5)limit_rate
        • (6)limit_rate_after
        • (7)執行個體
      • 4、limit_req 子產品
        • (1)流量控制的概念
        • (1)limit_req_zone
        • (2)limit_req
        • (3)執行個體
      • 5、處理突發
        • (1)為什麼要使用burst
        • (2)執行個體
      • 6、配置流量控制相關功能
        • (1)配置日志記錄
        • (2)發送到用戶端的錯誤代碼
    • 二、通路控制
      • 1、Nginx通路控制子產品類型
      • 2、基于IP子產品
      • 3、location拒絕所有請求
      • 4、使用者的信任登入

前言

一、Nginx限流

1、簡介

主要是當通路量達到一個限制量的時候可以選擇以伺服器為主要,而選擇對使用者通路請求的量做限制,對于超出限制的使用者請求會采取丢棄或者延遲處理等方式處理,來保證更多使用者來通路處理。

比如:某一伺服器正常在高峰期上能支援的通路量是1w,但是突然某一時刻在通路量上突然暴增一下子超過3w,5w則可能會導緻伺服器當機,這個時候我們 就可以通過設定最大的通路如1分鐘通路8000次。

也可以防止攻擊(對同一個ip每秒通路多少次)如:30min/次。

對應子產品

  • limit_conn_module 限制連接配接數
  • limit_req_module 限制請求頻率

2、關于 limit_req 和 limit_conn 的差別

limit_req

limit_conn

兩個子產品都是為了來限流的,但是兩者不在一個層面,為了搞清楚這個,必須先要弄清楚

request

connection

的差別,因為在很多情況下,我們把他們混淆了。

  • connection是連接配接,即常說的tcp連接配接,通過三次握手而建立的一個完整狀态機。建立一個連接配接,必須得要三次握手。
  • request是指請求,即http請求,(注意,tcp連接配接是有狀态的,而建構在tcp之上的http卻是無狀态的協定)。

通過打開一個網頁,然後通過wireshark可以看到,一個連接配接建立後(即三次握手後),在這個連接配接斷開之前(即四次揮手之前),會有很多的 http request,

這就是它們的差別:即一個連接配接的生命周期中,會存在一個或者多個請求,這是為了加快效率,避免每次請求都要三次握手建立連接配接,現在的HTTP/1.1協定都支援這種特性,稱為長連接配接(keepalive)。

3、limit_conn 子產品

通過 limit_zone 子產品來達到限制使用者的連接配接數的目的,即限制同一使用者 IP 位址的并發連接配接數。

Nginx 如何限流和通路控制(詳解)

對于提供下載下傳的網站,肯定是要進行流量控制的。Nginx 通過 core子產品的 limit_rate 等指令可以做到限流的目的。

Nginx 如何限流和通路控制(詳解)

(1)limit_conn_zone

文法:limit_conn_zone key zone=name:size;
預設:no
區域:http
功能:該指令定義一個 zone,該 zone 存儲會話的狀态。
           

說明:

  • key 是 Nginx 中的變量,通常為 binaryremoteaddr|server_name;
  • name 為共享記憶體的名稱,size 為該共享記憶體的大小;此配置會申請一塊共享記憶體空間 name,并且儲存 key 的通路情況。

(2)limit_conn

文法:limit_conn zone_name number
配置上下文:http,server,location
           

說明:

  • 使用 zone_name 進行通路并發控制,當超過 number 時傳回對應的錯誤碼

(3)limit_conn_log_level

文法:limit_conn_log_level info|notice|warn|error
預設值:error
配置上下文:http,server,location
           

說明:

  • 當通路達到最大限制之後,會将通路情況記錄在日志中

(4)limit_conn_status code

文法:limit_conn_status code
預設值:503
配置上下文:http,server,location
           

說明:

  • 當通路超過限制 number 時,給用戶端傳回的錯誤碼,此錯誤碼可以配合 error_page 等參數,在通路超量時給客戶傳回友好的錯誤頁面

(5)limit_rate

文法:limit_rate speed;
預設值:no
使用環境:http、server、location
示例: limit_rate 512k;
           

說明:

  • 對每個連結的速率進行限制,rate 表示每秒的下載下傳速度;

(6)limit_rate_after

文法:limit_rate_after size;
預設值:limit_rate_after 1m;
使用環境:http、server、location
示例:limit_rate_after 3m;
           

說明:

  • 此指令和 limit_rate 配合,當流量超過 size 之後,limit_rate 才開始生效

(7)執行個體

limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
  listen    80;
  server_name www.domain.com;
  root  /path/;
  index index.html index.htm;
  location /ip {
   limit_conn_status 503; # 超限制後傳回的狀态碼;
   limit_conn_log_level warn; # 日志記錄級别
   limit_rate 50; # 帶寬限制
   limit_conn addr 1; # 控制并發通路
  }
  # 當超過并發通路限制時,傳回503錯誤頁面
  error_page 503 /503.html;
}
           

4、limit_req 子產品

使用 ngx_http_limit_req_module 子產品可以 限制某一 IP 在一段時間内對伺服器發起請求的連接配接數,該子產品為用來做流量控制。

(1)流量控制的概念

流量限制 (rate-limiting),它可以用來限制用戶端在指定時間内 HTTP 請求的數量。請求可以是GET 請求,也可以是登入表單的 POST 請求。

流量限制可以用作安全目的,如減慢暴力密碼破解速率等。通過将傳入請求的速率限制為真實使用者的典型值,并辨別目标 URL 位址(通過日志),還可以用來抵禦 DDOS 攻擊,該功能可以用來保護上遊應用伺服器不被同時太多使用者請求所壓垮。

Nginx 流量限制使用漏桶算法(leaky bucket algorithm),漏桶算法在通訊和分組交換計算機網絡中廣泛使用,用于處理帶寬有限時的突發情況。

Nginx 如何限流和通路控制(詳解)
  • limit_req_zone

    指令定義了流量限制相關的參數
  • limit_req

    指令在出現的上下文中啟用流量限制。
Nginx 如何限流和通路控制(詳解)

該子產品主要控制機關時間内的請求數。使用 “leaky bucket” (漏鬥)算法進行過濾,在設定好限制 rate 之後,當機關時間内請求數超過 rate 時,子產品會檢測 burst 值,如果值為0,則請求會依據 delay|nodelay 配置傳回錯誤或者進行等待;如果 burst 大于0時,當請求數大于 rate 但小于 burst 時,請求進入等待隊列進行處理。

(1)limit_req_zone

文法:limit_req_zone key zone=name:size rate=rate
配置上下文:http
           

說明:

  • key 是 Nginx 中的變量,通常為

    binary_remote_addr

    |

    server_name

  • name 為共享記憶體的名稱,size 為該共享記憶體的大小;
  • rate 為通路頻率,機關為 r/s 、r/m 。此配置會申請一塊共享記憶體空間 name,并且儲存 $key 的通路情況;

(2)limit_req

文法: limit_rate zone=name [burst=number] [nodelay|delay=number]
配置上下文:http,server,location
           

說明:

  • 開啟限制,burst設定最多容量,nodelay決定當請求超量時,是等待處理還是傳回錯誤碼;

(3)執行個體

limit_req_zone $binary_remote_addr zone=req:10m rate=2r/m;
server {
  listen    80;
  server_name www.domain.com;
  root  /path/;
  index index.html index.htm;
  location /limit {
   limit_req zone=req burst=3 nodelay;
  }
  # 當超過并發通路限制時,傳回503錯誤頁面
  error_page 503 /503.html;
}
           

注意:

這兩種通路控制都需要申請記憶體空間,既然有記憶體空間,當然會存在記憶體耗盡的情況,這時新的請求都會被傳回錯誤,是以當開啟通路量限制時,需要通過監控防止此類情況發生。

5、處理突發

(1)為什麼要使用burst

如果我們在1000毫秒内接收到2個請求,怎麼辦?對于第二個請求,Nginx将給用戶端傳回錯誤。這可能并不是我們想要的結果,因為應用本質上趨向于突發性。

相反地,我們希望緩沖任何超額的請求,然後及時地處理它們。我們更新下配置,在

limit_req

中使用

burst

參數。

(2)執行個體

Nginx 如何限流和通路控制(詳解)

burst

參數定義了超出zone指定速率的情況下(示例中的

addr

區域,速率限制在每秒1個請求),用戶端還能發起多少請求。上一個請求1000毫秒内到達的請求将會被放入隊列,我們将隊列大小設定為5。

這意味着,如果從一個給定IP位址發送6個請求,Nginx會立即将第一個請求發送到上遊伺服器群,然後将餘下5個請求放在隊列中。然後每1000毫秒轉發一個排隊的請求,隻有當傳入請求使隊列中排隊的請求數超過5時,Nginx才會向用戶端傳回錯誤。

6、配置流量控制相關功能

(1)配置日志記錄

預設情況下,Nginx會在日志中記錄由于流量限制而延遲或丢棄的請求,如下所示:

日志條目中包含的字段:

  • limiting requests - 表明日志條目記錄的是被“流量限制”請求
  • excess - 每毫秒超過對應“流量限制”配置的請求數量
  • zone - 定義實施“流量限制”的區域
  • client - 發起請求的用戶端IP位址
  • server - 伺服器IP位址或主機名
  • request - 用戶端發起的實際HTTP請求
  • host - HTTP報頭中host的值

預設情況下,Nginx以

error

級别來記錄被拒絕的請求,如上面示例中的

[error]

所示(Nginx以較低級别記錄延時請求,一般是

info

級别)。如要更改Nginx的日志記錄級别,需要使用

limit_req_log_level

指令。這裡,我們将被拒絕請求的日志記錄級别設定為

warn

(一定要定義日志位置和級别才可以)

  • 錯誤日志級别設定為warn
    Nginx 如何限流和通路控制(詳解)
  • limit_req_log_level日志級别設定為warn
    Nginx 如何限流和通路控制(詳解)
  • 繼續通路測試,看error.log日志
    Nginx 如何限流和通路控制(詳解)

(2)發送到用戶端的錯誤代碼

一般情況下,用戶端超過配置的流量限制時,Nginx響應狀态碼為503(Service Temporarily Unavailable)。可以使用

limit_req_status

指令來設定為其它狀态碼(例如下面的404狀态碼):

  • 修改配置檔案
    Nginx 如何限流和通路控制(詳解)
  • 修改前
    Nginx 如何限流和通路控制(詳解)
  • 修改後
    Nginx 如何限流和通路控制(詳解)

二、通路控制

1、Nginx通路控制子產品類型

  • 基于IP的通路控制:

    http_access_module

  • 基于使用者的信任登入:

    http_auth_basic_module

2、基于IP子產品

配置文法:

Syntax:allow address | CIDR | unix: | all;
default:預設無
Context:http,server,location

Syntax:deny address | CIDR | unix: | all;
default:預設無
Context:http,server,location
           

配置設定:

#vim /etc/nginx/conf.d/access_mod.conf  //修改配置檔案

  server {
           listen 80;
           server_name localhost;
           location ~ ^/admin {
                  root /home/www/html;
                  index index.html index.hml;
                  deny 192.168.239.128;      //拒絕192.168.239.128通路
                  allow all;
           }
  }
 #如果先允許通路,在定義拒絕通路,那麼拒絕通路不生效。
           

3、location拒絕所有請求

server {
        listen 80;
        server_name localhost;
        location /foo.html {
             root /home/www/html;
             deny all;
        }
}
           

4、使用者的信任登入

Syntax:auth_basic string | off;
default:auth_basic off;
Context:http,server,location,limit_except

Syntax:auth_basic_user_file file;
default:預設無
Context:http,server,location,limit_except
file:存儲使用者名密碼資訊的檔案。
           

配置執行個體

#mv access_mod.conf auth_mod.conf   //修改配置檔案
server {
        listen 80;
        server_name localhost;
        location ~ ^/admin {
           root /home/www/html;
           index index.html index.hml;
           auth_basic "Auth access test!";
           auth_basic_user_file /etc/nginx/auth_conf;
        }
}
#auth_basic不為off,開啟登入驗證功能,auth_basic_user-file加載賬号密碼檔案
           

建立密碼檔案

$ mkdir /home/www/html/admin -p
$ vim /home/www/html/admin/index.html
hello boy
$ yum -y install httpd-tools    //htpasswd使開源http伺服器apache httpd的一個指令工具,用于生成http基本認證的密碼檔案
$ htpasswd -cm /etc/nginx/auth_conf user1   //第一次建立使用者
$ htpasswd -m  /etc/nginx/auth_conf user2   //第二次建立使用者
$ cat /etc/nginx/auth_conf    //檢視建立的使用者的密碼
user1:$apr1$MOa9UVqF$RlYRMk7eprViEpNtDV0n40
user2:$apr1$biHJhW03$xboNUJgHME6yDd17gkQNb0
           

5、通路測試

繼續閱讀