壓力測試報告
在beta階段尾聲時,我們對網站進行了一次壓力測試。同時我們也對alpha發布以及去年的產品做了同樣的測試進行對比。測試代碼可以參考我們上一篇測試工具介紹的博客。
測試環境與項目
我們使用了一台vultr服務器進行測試,配置為1c/1G RAM+1G swap/1Tbps/LA,與生產環境相同,測試時間為凌晨2點左右,確保盡量不影響正常用戶以及性能瓶頸不在測試服務器上。測試環境與生產環境相對獨立,是當時生產環境的快照,確保用戶資料的安全性。在測試時我們臨時禁用了CSRF,CROS,IP訪問限制以及CDN。我們做了以下測試,測試了去年的網站以及alpha(被攻擊修改后),beta階段的網站:
編號 | 內容 | 目的 |
---|---|---|
1 | 使用siege,並發發起1000個請求,訪問首頁。 | 測試網站的並發處理能力 |
2 | 使用siege和自己的腳本,並發發起1000個請求,訪問獲取評分接口。 | 測試網站緩存及高資源占用接口處理能力 |
3 | 使用自己的腳本,持續10秒,每秒發起200個請求,訪問搜索課程接口 | 測試長時間較大壓力的情況(有緩存) |
4 | 使用自己的腳本,發起1000個請求,向“數據庫技術基礎”課程評論評分 | 數據庫壓力測試 |
5 | 使用自己的腳本,發起2000個請求,隨機訪問搜索頁面,記錄執行時間,成功率 | 綜合測試數據庫,緩存,網站 |
自己的測試程序基本結構如下:
import requests
import threading
import time
class thread1(threading.Thread):
count200=0
count502=0
count504=0
count500=0
countelse=0
def __init__(self, threadID, name):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
def run(self):
time.sleep(15)
a = requests.get(TEST_URL)
code = a.status_code
else:
pass
if int(code)==200:
thread1.count200+=1
elif int(code)==502:
thread1.count502+=1
elif int(code)==504:
thread1.count504+=1
elif int(code)==500:
thread1.count500+=1
else:
print(code)
thread1.countelse+=1
if __name__=="__main__":
True
threads=[]
for i in range(2000):
thread=thread1(i, "Thread-{}".format(i))
threads.append(thread)
a=time.time()
for i in threads:
i.start()
time.sleep(0.005)
time.sleep(50)
print(thread1.count200,thread1.count502,thread1.count504,thread1.count500,thread1.countelse)
測試結果
測試1
階段 | 成功次數 | 成功率 |
---|---|---|
去年 | 186 | 18.6% |
alpha | 1000 | 100% |
beta | 998 | 99.8% |
我們認為有兩次請求未成功可能是誤差,alpha與beta階段在主頁代碼與緩存邏輯上未做大量修改。總的來說,就去年的網頁有較大的提升,主要原因是我們將頁面渲染從服務器端調整到了客戶端。
測試2
階段 | 成功次數 | 成功率 | HTTP502 | HTTP504 | HTTP500 | else |
---|---|---|---|---|---|---|
去年 | 沒有這個接口 | - | - | - | - | - |
alpha | 527 | 52.7% | 466 | 0 | 5 | 2 |
beta | 911 | 91.1% | 89 | 0 | 0 | 0 |
可以看到,我們的beta階段比起alpha有了不小的提升,主要是因為我們優化了緩存方式,建立了專用的緩存表。
測試三
階段 | 成功次數 | 成功率 | HTTP502 | HTTP504 | HTTP500 | else |
---|---|---|---|---|---|---|
去年 | 0 | 0% | 362 | 961 | 677 | 0 |
alpha | 1645 | 62.25% | 108 | 121 | 126 | 0 |
beta | 1750 | 87.5% | 156 | 94 | 0 | 0 |
去年的程序絲毫沒有考慮緩存的情況,因此在高計算資源需求接口發生並發時就直接炸了。后來經過手動測試,去年的接口並發大概在10左右。
beta相較於alpha主要是緩存方式略微優化,因此差別較小。
測試四
階段 | 成功次數 | 成功率 | HTTP502 | HTTP504 | HTTP500 | else |
---|---|---|---|---|---|---|
去年 | 無法運行此接口 | - | - | - | - | - |
alpha | 597 | 59.7% | 403 | 0 | 0 | 0 |
beta | 923 | 92.3% | 77 | 0 | 0 | 0 |
去年的程序無法成功調試出這個接口,因此未做測試。
事實上我們beta階段與alpha階段評論接口未作什么修改,然而成功率差距較大。我們猜想原因是上次被攻擊后數據庫中留有大量信息,盡管被邏輯上刪除了,但是物理上依然存在,因此拖慢了速度,類似上次數據庫評測中sqlite3在較大數據規模下的插入時間。
測試五
階段 | 成功次數 | 成功率 | HTTP502 | HTTP504 | HTTP500 | else |
---|---|---|---|---|---|---|
去年 | 0 | 0% | - | - | - | - |
alpha | 1023 | 51.15% | 333 | 600 | 44 | 0 |
beta | 1525 | 76.25% | 143 | 115 | 0 | 217 |
與測試三的原因類似,去年的程序此接口的並發極低。
相較於測試三,這個測試考慮了無緩存的情況。我們對於搜索所有課程是默認有緩存的,而隨機搜索的第一次是無緩存的,因此負載會大不少。這個接口仍然有不小的改進空間。
總結
總的來說,我們的網站現階段在200並發下達到了90%左右的可用性。在實際應用中,我們的網站很少會遇到這種強度的並發,我們的小時活躍量在10左右。此外,在遇到惡意攻擊時我們已經有了應對經驗,能快速解決問題。
因此我們認為我們的網站在壓力測試下表現良好,符合預期目標。