1. 程式人生 > 其它 >Nginx防止大流量攻擊,限制流量訪問(limit_req_zone模組)以及進行網站壓力測試

Nginx防止大流量攻擊,限制流量訪問(limit_req_zone模組)以及進行網站壓力測試

技術標籤:運維限流運維ddoslinux

文章目錄

一、限流的幾種演算法

(一)、計數器演算法

採用計數器實現限流有點簡單粗暴,一般我們會限制一秒鐘之內能夠通過的請求數,比如限流 qps(每秒查詢率)為100,演算法的實現思路就是從第一個請求進來開始計時,在接下去的1s內,每來一個請求,就把計數加1,如果累加的數字達到了100,那麼後續的請求就會被全部拒絕。等到1s結束後,把計數恢復成0,重新開始計數。

這種實現方式,有一個明顯的弊端:如果在單位時間1s內的前10ms,已經通過了100個請求,那後面的990ms,只能眼巴巴的把請求拒絕,我們把這種現象稱為“突刺現象”。

(二)、漏桶演算法

為了消除"突刺現象",可以採用漏桶演算法實現限流,漏桶演算法這個名字就很形象,演算法內部有一個容器,類似生活用到的漏斗,當請求進來時,相當於水倒入漏斗,然後從下端小口慢慢勻速的流出。不管上面流量多大,下面流出的速度始終保持不變。
不管服務呼叫方多麼不穩定,通過漏桶演算法進行限流,每10毫秒處理一次請求。因為處理的速度是固定的,請求進來的速度是未知的,可能突然進來很多請求,沒來得及處理的請求就先放在桶裡,既然是個桶,肯定是有容量上限,如果桶滿了,那麼新進來的請求就丟棄。

簡單理解為:

  • 水(請求)從上方倒入水桶,從水桶下方流出(被處理);
  • 來不及流出的水存在水桶中(緩衝),以固定速率流出;
  • 水桶滿後水溢位(丟棄)。
  • 這個演算法的核心是:快取請求、勻速處理、多餘的請求直接丟棄。
  • 相比漏桶演算法,令牌桶演算法不同之處在於它不但有一隻“桶”,還有個佇列,這個桶是用來存放令牌的,佇列才是用來存放請求的。

(三)、令牌桶演算法

從某種意義上講,令牌桶演算法是對漏桶演算法的一種改進,漏桶演算法能夠限制請求呼叫的速率,而令牌桶演算法能夠在限制呼叫的平均速率的同時還允許一定程度的突發呼叫。
在令牌桶演算法中,存在一個桶,用來存放固定數量的令牌。演算法中存在一種機制,以一定的速率往桶中放令牌。每次請求呼叫需要先獲取令牌,只有拿到令牌,才有機會繼續執行,否則就只能選擇等待可用的令牌、或者直接拒絕。

放令牌這個動作是持續不斷的進行,如果桶中令牌數達到上限,就丟棄令牌,所以就存在這種情況,桶中一直有大量的可用令牌,這時進來的請求就可以直接拿到令牌執行,比如設定 qps(每秒查詢率)為100,那麼限流器初始化完成一秒後,桶中就已經有100個令牌了,這時服務還沒完全啟動好,等啟動完成對外提供服務時,該限流器可以抵擋瞬時的100個請求。所以,只有桶中沒有令牌時,請求才會進行等待,最後相當於以一定的速率執行。

簡單理解為:

  • 令牌以固定速率產生,並快取到令牌桶中;
  • 令牌桶放滿時,多餘的令牌被丟棄;
  • 請求要消耗等比例的令牌才能被處理;
  • 令牌不夠時,請求被快取或者被拒絕

二、 limit_req_zone 引數配置

http {
    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    #限流模組配置
     limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;

第一個引數:$binary_remote_addr 表示通過remote_addr這個標識來做限制,“binary_”的目的是縮寫記憶體佔用量,
          是限制同一客戶端ip地址。
第二個引數:zone=one:10m 表示生成一個大小為10M,名字為one的記憶體區域,用來儲存訪問的頻次資訊。
第三個引數:rate=1r/s 表示允許相同標識的客戶端的訪問頻次,這裡限制的是每秒1次,還可以有比如30r/m的。

------------------------------------------------------------------------------------------------------

server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            limit_req zone=one burst=3 nodelay;
			limit_req_status 598;
            root   html;
            index  index.html index.htm;
        }

第一個引數:zone=one 設定使用哪個配置區域來做限制,與上面limit_req_zone 裡的 one 對應。
第二個引數:burst=3,重點說明一下這個配置,burst爆發的意思,這個配置的意思是設定一個大小為3的緩衝區當有大量請
          求(爆發)過來時,超過了訪問頻次限制的請求可以先放到這個緩衝區內。
第三個引數:nodelay,如果設定,超過訪問頻次而且緩衝區也滿了的時候就會直接返回503,如果沒有設定,則所有請求會等待排隊。
第四個引數:limit_req_status為自定義返回值,當流量被拒絕後返回598

三、limit_conn_module 引數配置

這個模組用來限制單個IP的請求數。並非所有的連線都被計數。只有在伺服器處理了請求並且已經讀取了整個請求頭時,連線才被計數。

limit_conn_zone $binary_remote_addr zone=addr:10m;

server {
    location /download/ {
        limit_conn addr 1;
    }

一次只允許每個IP地址一個連線。

limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;

server {
    ...
    limit_conn perip 10;
    limit_conn perserver 100;
}

可以配置多個limit_conn指令。例如,以上配置將限制每個客戶端IP連線到伺服器的數量,同時限制連線到虛擬伺服器的總數。

limit_conn_zone $binary_remote_addr zone=addr:10m;

這裡,客戶端IP地址作為關鍵。請注意,不是$ remote_addr,而是使用$ binary_remote_addr變數。 $ remote_addr變數的大小可以從7到15個位元組不等。儲存的狀態在32位平臺上佔用32或64位元組的記憶體,在64位平臺上總是佔用64位元組。對於IPv4地址,$ binary_remote_addr變數的大小始終為4個位元組,對於IPv6地址則為16個位元組。儲存狀態在32位平臺上始終佔用32或64個位元組,在64位平臺上佔用64個位元組。一個兆位元組的區域可以保持大約32000個32位元組的狀態或大約16000個64位元組的狀態。如果區域儲存耗盡,伺服器會將錯誤返回給所有其他請求。

Syntax: limit_conn_log_level info | notice | warn | error;
Default:    
limit_conn_log_level error;     #當伺服器限制連線數時,設定所需的日誌記錄級別。
Context:    http, server, location
Syntax: limit_conn_status code;
Default:    
limit_conn_status 503;      #設定拒絕請求的返回值。
Context:    http, server, location

四、網站壓力測試

Webbench是一個在linux下使用的非常簡單的網站壓測工具。它使用fork()模擬多個客戶端同時訪問我們設定的URL,測試網站在壓力下工作的效能,最多可以模擬3萬個併發連線去測試網站的負載能力。

Apache ab(Apache Bench效能測試工具,這是apache免費自帶的效能測試工具,就在apache的bin目錄下,它能模擬多個併發請求,也就是說它主要是用來測試你的網站每秒能處理多少請求的。

1、安裝Webbench

yum install gcc make ctags -y

#安裝Webbench
wget https://www.moerats.com/usr/down/webbench-1.5.tar.gz
tar zxvf webbench-1.5.tar.gz

mkdir /use/local/man
cd man/
touch man1
 
cd ~/webbench-1.5
make && make install


2、使用 Webbench
#使用幫助
webbench -h
#測試命令,-c為併發數;-t為測試時長,單位秒;後面為連結
webbench -c 800 -t 20 http://www.baidu.com/

3、使用apache ab
需要提前安裝apache:
yum install -y httpd

#使用幫助
ab -h
#測試1,-n為傳送請求次數;-c併發數;後面為連結
ab -n 200 -c 100 http://www.baidu.com/
#測試2,-t為測試時長,單位秒;-c併發數;後面為連結
ab -t 70 -c 30 http://www.baidu.com/