1. 程式人生 > 實用技巧 >Nginx限流配置方法 限流策略 & Python壓力測試程式碼

Nginx限流配置方法 限流策略 & Python壓力測試程式碼

最近有空了解了下Nginx的限流策略,查了一些網上的資料,發現很多對引數的描述並不準確,所以自己抽空做了些測試,分享下心得。

1、配置限流策略

http {
    #Nginx限流。語法:limit_req_zone  key  zone  rate      
    #引數說明 key: 定義需要限流的物件($binary_remote_addr表示基於客戶端ip(remote_addr)進行限流,binary_表示壓縮記憶體佔用量)  
    #引數說明 zone: 定義共享記憶體區來儲存訪問資訊(定義了一個大小為10M的記憶體區,用於儲存IP地址訪問資訊。)
    #引數說明 rate: 用於設定每個IP的最大訪問速率(rate
=5r/s表示每秒處理5個請求,rate=30r/m表示每分鐘處理30個,即每2秒1個。) limit_req_zone $binary_remote_addr zone=myLimitS2:10m rate=2r/s; #記憶體區名為myLimitS2,每秒處理2個請求 limit_req_zone $binary_remote_addr zone=myLimitS10:10m rate=10r/s; #記憶體區名為myLimitS10,每秒處理10個請求 limit_req_zone $binary_remote_addr zone=myLimitS20:10m rate=20r/s; #記憶體區名為myLimitS20,每秒處理20個請求 limit_req_zone $binary_remote_addr zone=myLimitS30:10m rate=30r/s; #記憶體區名為myLimitS30,每秒處理30個請求 limit_req_zone $binary_remote_addr zone=myLimitS40:10m rate=40r/s; #記憶體區名為myLimitS40,每秒處理40個請求 limit_req_zone $binary_remote_addr zone=myLimitS50:10m rate=50r/s; #記憶體區名為myLimitS50,每秒處理50個請求 }

2、應用限流策略

2.1、延時

server {
    location / {
        limit_req zone=myLimitS2 burst=25; 
        #設定漏桶併發量burst=25,併發請求超過burst的會直接返回limit_req_status,burst以內的請求會按rate設定的速度排隊處理,新的請求會排隊等待,新請求併發超出burst的同樣會被阻止。
     #limit_req_status 503; #自定義返回狀態
  }
}

2.2、不延時

server{
    location / {
        limit_req zone
=myLimitS2 burst=40 nodelay; #設定漏桶併發量burst=40,瞬間處理能力為qps=burst=40,併發請求數<=40時都會同時被處理;但由於初始qps=2,所以會在burst/qps=40/2=20秒內以rate設定的速度處理漏桶;如果有新請求過來會依次進入漏桶,超過漏桶容量的會返回limit_req_status #limit_req_status 503; #自定義返回狀態 } }

注意:設定的burst與實際測量出來的burst可能有±2左右的偏差,可以忽略。

3、Python壓力測試程式碼(本人python菜雞,借鑑的忘了哪位大神的程式碼,感謝)

import datetime
import json
import requests
import logging
import threading
import time
import sys
from time import sleep, ctime

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

reponse_time = []
OK = []
errorCount = []

class runScript():
    def API(self, url, params):
        try:
            r = requests.get(url, params=params, timeout=10)
            #print(r.status_code)
            code = r.status_code
            if code != 200:
                print(code)
                errorCount.append[1]
            else:
                js = json.dumps(r.json())
                #print(r.json()) #json格式的響應資料
                # print(r.elapsed.total_seconds()) 響應時間
                #print("ooo" + js) #沒有解碼的響應資料
                return [r.json(), r.elapsed.total_seconds(), js]
            #r.raise_for_status()  # 如果響應狀態碼不是 200,就主動丟擲異常
        except requests.RequestException as e:
            print('failed.' + e)
            errorCount.append[1]

    def circulation(self, url, params):
        status = 0
        datas = "none."
        try:
            obj = self.API(url, params)
            if obj != None:
                #print(obj)
                reponse_time.append(obj[1])
                datas = json.loads(obj[2])["Msg"]
                status = json.loads(obj[2])["Code"]
                OK.append(datas)
        except Exception as e:
            return

def test(url, params):
    Restime = runScript()
    Restime.circulation(url, params)


def main(num, url, params):
    print("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓")
    start_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S %f')
    threads = []
    for i in range(num):
        t = threading.Thread(target=test, args=(url, params))
        threads.append(t)
    for t in range(num):
        threads[t].start()
        #time.sleep(0.0001)
    for j in range(num):
        threads[j].join()
    print("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑")
    print("Starting at:", start_time)
    print("All done at:", datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S %f'))
    # print(OK)
    print('執行緒數:', len(threads))
    print('響應次數:', len(reponse_time))
    print('正常響應次數:', len(OK))
    print('錯誤次數:', len(errorCount))
    print('總響應最大時長:', (0 if len(reponse_time)==0 else max(reponse_time)))
    print('總響應最小時長:', (0 if len(reponse_time)==0 else min(reponse_time)))
    print('總響應時長:', (0 if len(reponse_time)==0 else sum(reponse_time)))
    print('平均響應時長:', (0 if len(reponse_time)==0 else (sum(reponse_time) / len(reponse_time))))
    # print('QPS(TPS)= 併發數/平均響應時間:',num  / (sum(reponse_time) / len(reponse_time)))


if __name__ == '__main__':
    num = input('輸入需要開啟的執行緒數量:')
    url = 'http://192.168.11.35:8598/test.html'  # 地址
    #params = {'UserName': 'admin', 'UserPwd': '123456'}  # 引數
    main(int(num), url, params)

python測試結果預覽:

輸入需要開啟的執行緒數量:50

Starting at: 2020-09-17 11:18:33 909979 All done at: 2020-09-17 11:18:43 978149 執行緒數: 50 響應次數: 21 正常響應次數: 21 錯誤次數: 0 總響應最大時長: 9.978622 總響應最小時長: 0.946371 總響應時長: 106.58336500000001 平均響應時長: 5.075398333333334